PHPの最近のブログ記事

うちは PHP を使った開発はあまりしないので、開発機の PHP はほったらかしのことが多いのだが、そのサーバを使っているお客さんから「最新の WordPress が入らないのでバージョンアップを」との要請あり。

じゃあ、PHP 7系の最新に・・・と思ったのだが、お客さん都合で「5.6系の最新に」ということになった。

で、PHP を 5.6 に上げたのだが、その後、phpMyAdmin の新規インストールに若干ハマったのでメモ。

現在、この開発機(CentOS 6.9)は「基本的にソースからコンパイルは無し。なるべく yum でパッケージインストール」というルールで運用しているため、今回も yum を使って PHP や phpMyAdmin をインストールした。

問題は phpMyAdmin をインストールしたときに発生した。

# yum --enablerepo=epel install -y phpMyAdmin

と、epel リポジトリを使ってインストールしようとすると、必要な依存ファイルがバージョン 5.6.40 用だから駄目だと怒られる。
確かに PHP は 5.3.3 から 5.6.40 にアップデートした。しかし、epel リポジトリの phpMyAdmin は 5.3.3 用のようだ。

 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

とか言われるし(^^; 問題あるパッケージは無視して強引に入れちゃえよって???

こりゃあかんと、次は、

# yum -y --enablerepo=remi,remi-php56 install phpMyAdmin

と、remi 及び remi-php56 リポジトリを使ってインストール。すると、今度は 依存ファイルはバージョン 7.0以上の PHP 用じゃないとあかんと怒られるのである。
どうも、PHP 7系用の phpMyAdmin をインストールしようとしているようだ・・・

結局、remi リポジトリにいる最新の phpMyAdmin は PHP 7系用ということなんよねぇ。
なので、解としては、PHP 5.6系用のパッケージが存在しているリポジトリのみを利用すればいいのである。

# yum -y --enablerepo=remi-php56 install phpMyAdmin

これでやっと phpMyAdmin が無事にインストールされたのであった。

という、ぷちハマリの話なのである。
ちょっと他人の書いた PHP の修正案件があったので、メモ。

UTF-8 で書かれた PHP ソースの中で、以下のような記述でメールの送信を行っている。

$w_from = "From: ほげほげ星人 <no-reply@exsample.jp>";
$w_to = "hogehoge@exsample.com"
$w_subject = "[返信]ありがとうございます";
$w_body = "あれやこれや...";

mb_language("Japanese");
mb_internal_encoding("UTF-8");

mb_send_mail($w_to, $w_subject, $w_body,  $w_from);

が、これ、実際にはむちゃくちゃな内容のメールが届く。

Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

とか言いながら本文は UTF-8 だし、FROM アドレスは MIME B エンコードされず、Subject だけは ISO-2022-JP で MIME B エンコードされているという状況である。

まあ、最近のメールソフト(Web メール含む)は charset の記述を無視して、実際に本文の文字コードをチェックして表示を行うものが多いから、こんな状況でも一見、ちゃんと表示されてたりするので大丈夫・・・というか、質が悪いな、これ(^^;
なんのための、charset 指定だっつうの(^^;

どうも、UTF-8 のメールを送りたいようなので、

$w_from = "From: ほげほげ星人 <no-reply@exsample.jp>";
$w_to = "hogehoge@exsample.com"
$w_subject = "[返信]ありがとうございます";
$w_body = "あれやこれや...";

header('Content-Type: text/html; charset=UTF-8');
header('Content_Language: ja');

mb_language("uni");
mb_internal_encoding("UTF-8");

mb_send_mail($w_to, $w_subject, $w_body,  $w_from);

という具合に、Content-Type ヘッダーを明示的に指定し、mb_language は Japanese ではなく uni を指定してやれば、Subject は UTF-8 で MIME B エンコードされるし、

Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: BASE64

という Content-Type がセットされて、本文との整合性が取れる。

いや、俺の世代だと、そもそも UTF-8 のメールというのがすでに気持ち悪いのだけど、これも時代の流れ(^^;

・・・あ、うまくいったと思ったけど、これだと From アドレスは MIME B エンコードされないままだな。
そこは自前でエンコードしてからセットしてやる必要があるのか。ふむふむ。

$w_from = "From: " . mb_encode_mimeheader("ほげほげ星人", "UTF-8", "B") . " <no-reply@exsample.jp>";

だな。
そうか(^^;

PHP の round 関数に mode パラメータが追加されたのは 5.3.0 からか。
うちの一番 PHP のバージョンの古いサーバでテストしてたからエラーになってたんやな(^^;

まあ、それは良いとして、mode で PHP_ROUND_HALF_UP を指定したら、Excel 関数の ROUNDUP と同じ動きをしてくれるのかと思ってたら違うのね。

Excel 関数で

=ROUNDUP(1.05, 0)

とすれば、セルには 2 が表示される。

これと同じことを PHP でしたかったので、

round(1.05, 0, PHP_ROUND_HALF_UP)

としてみたけど、計算結果は 1。
うーん(^^;これ違うんだな。

ちなみに、

round(1.05, 0, PHP_ROUND_HALF_UP)
round(1.05, 0, PHP_ROUND_HALF_DOWN)
round(1.05, 0, PHP_ROUND_HALF_EVEN)
round(1.05, 0, PHP_ROUND_HALF_ODD)

このどれでも結果は 1 であります。

はぁ?っと思ったら、PHP ではこういう場合 ceil 関数を使うんだね。

ceil(1.05)

で、バッチリでありやした。(結局、round 関数の話じゃなくなったな(^^;)
他人様が作られた PHP ソースに「文字数チェック入れてもらえますか」と依頼があったので、

$w_len = mb_strlen($word);
if ($w_len > 300) {
Fnc_Err_Html("エラー","文字数が300文字を超えています。(" . $w_len . "文字)" );
}

とコードを追加しといたんだけど、何か、全角文字の時挙動がおかしい。

300文字を超えたらエラーになるようにしてるのに、200文字でもエラーになるし(^^;
600文字あると判断されてる様子。完全に、UTF-8 の全角1文字を3文字としてカウントしてる。コードが UTF-8 だとちゃんと認識してないから、全角1文字を構成する3バイトを3文字と判断してるんだな。

mb_strlen は第二引数に文字コードを指定できるが、指定しなきゃ内部コードを採用するはず。
ソースも UTF-8 で書かれているし、受け取るデータも UTF-8 である。なのに UTF-8 だと認識できていない・・・はぁ???

ググってみると、どうも、mb_strlen は文字コードが UTF-8 の時に限り、明示的にコードを指定しないといけないようだ・・・

明かなバグやないか(^^;

たまにしか PHP 使わないので知らんかったワ(^^;;;

$w_len = mb_strlen($word, "UTF-8");

とすれば OK であった・・・何やねん(^^;
あれこれ試した時間を返せ、こんにゃろ!(^^;

ところで、Web のフォーム入力されたデータを受け取ってるんだけど、フォームの入力中も文字数をチェックしてる。JavaScript でね。
で、JavaScript のチェックではOKになったデータが、PHP 側ではエラーになる。
どうも、JavaScript で document.form.hoge.value.length で取得すると「改行コード(CR+LF)は1文字として扱う」のに、mb_strlen は「CR と LF を1文字ずつ、計2文字として扱う」ようだ。
これも果てしなくバグ臭いのお(^^;
PHP プログラマは何も感じないのか、この仕様(^^;

まあ、これも、

$word = str_replace("\r\n", " ", $word);

してからチェックすればいいんだけど。

何だかなぁ~

<追記>
ああ、php -i してみたら、
mbstring.internal_encoding => no value => no value
になってんなあ。これだと、内部コードは ISO-8859-1 になっちゃうんかな?
ま、面倒くさがらず、mb_strlen の第二引数くらい設定しろってことやね(^^;すまん、すまん。
お客さんから「PDO の mysql ドライバ入れて!」と連絡あり。

うちの管理しているサーバの一つで、PHP プログラム動かそうとしたら「The mysql driver is not currently installed」って怒られたって。

ということで mysql driver をインストールしたわけだが、CentOS 4.8 のサーバなので、yum インストールしようにもリポジトリがもう正規の場所に無いし(^^;、設定変更するのも面倒なので手動でインストール。

# cd /usr/local/src
# /usr/local/bin/pecl download pdo_mysql
# tar xvfz PDO_MYSQL-1.0.2.tgz
# cd PDO_MYSQL-1.0.2
# /usr/local/bin/phpize
# ./configure --with-pdo-mysql=/usr/local/mysql
# make
# make install

で、すんなり入ったんだけど、/usr/local/lib/php.ini に、

extension = /usr/local/lib/php/extensions/no-debug-non-zts-20060613/pdo_mysql.so

って追加しても、一向に PDO mysql ドライバがロードされない。

# /usr/local/bin/php -i|grep PDO
PDO
PDO support => enabled
PDO drivers => sqlite2, sqlite
PDO Driver for SQLite 3.x => enabled

というまんま。

しばし悩んだが、結局、extension_dir の設定が、

extension_dir = /usr/lib64/php4

みたいに腐ってた(^^;
古い環境(PHP4系)から設定を移してる時、間違って入れちゃったんだな(^^;

これを、

extension_dir = /usr/local/lib/php/extensions
extension = no-debug-non-zts-20060613/pdo_mysql.so

みたいに設定してやれば、無事、

# /usr/local/bin/php -i|grep PDO
PDO
PDO support => enabled
PDO drivers => sqlite2, sqlite, mysql
PDO Driver for MySQL, client library version => 5.1.25-rc
PDO Driver for SQLite 3.x => enabled

となった。

う~む、php.ini の内容、一度ちゃんとチェックしといた方がええなあ(^^;;;
俺は「ショートタグなんか使うな!」と言われるようになってから PHP を触ることが多くなったもんで、ショートタグには違和感というか、悪感情しかない。使ったことがないんでね。

俺自身が絶対使うことはないし、うちから仕事を出した外注さんがショートタグ使って書いてきたら、無慈悲に作り直しを命じるだけである。(まあ、PHP開始タグを直すだけの話なんだから大したことじゃなけど)

まあ、最近はさすがに

<? phpinfo(); ?>

なんて書いてくる人はいなくなったけど、未だにに echo を書くのを、

<?= $hogehoge >

なんてする人はいる。

こんなの、<?php echo $hogehoge; > って書けばいいだけじゃん。'<?=' 使って、誰得?って思うんだけど、こういうのは、Perl の人が変数名省略するのと(要は $_ 使いたがるのと)一緒で、まあ、狭いコミュニティの中の「美学」があるんだろうけどなあ・・・

そんな美学、業務システム作る時には不要です。客先に納品する物は、省略せず、「冗長」にソースを書きましょう。

「省略の美学」は「自分一人だけで将来にわたってもメンテナンスするソース」だけで適用してください。

まあ、PHP 5.4 から、「ショートタグを許さない設定でも、<?= だけは許す」みたいな仕様になったみたいなんで、'<?='使いたいヤツって、糞みたいに多いんだろうなあ(^^;;;

いや、OpenID のサンプルコードの中にも一本だけ(discover.php)'<?='多用しているものがあったので書いてみました。(うちの PHP は 5.3.6 なので引っかかるのよ(^^;)

今時の PHP はディフォルトで、

short_open_tag = Off

って設定になってるのに、未だに <? echo 'hoge' ?> とか書いてくる人、頭おかしいの?親の教育がなってないわ!・・・とか思っちゃうわ、ホンマ(^^;

「すっきりしたソースになる」だって(笑)

お前、PHP しか知らない「Web プログラマ」だろ?

あのさあ、納品するソースはちゃんと「ディフォルト設定」で動くように書けよ。

お前が自宅のサーバで

short_open_tag = On

にしてプログラミングしてようが知ったこっちゃないけど、ユーザへの納品物を short open tag で書くのはやめろ。常識だろうが。

ホンマ、趣味の延長でプログラミングを仕事にしてる「Web プログラマ」は、「素人には冗長に見えても、『正しい』書き方で書くソースが一番美しい」ということに早く気づいてほしいわ。

仕事ではなく、自宅で趣味でプログラミングしている・・・っていう人は、好きなだけ short open tag 使ってください。

もう午前4時だ・・・俺はまだ十日市にいる。

ずっと PHP のインストールをしていたのだ。

今日時点で最新の PHP 5.3.8 をインストールしたところ、phpinfo の実行で、

Warning: phpinfo() [function.phpinfo]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Tokyo' for 'JST/9.0/no DST' instead in /var/apache/htdocs/test.php on line 1

というようなワーニングが出てしまう。
どうも、Default timezone と php.ini で設定している timezone が同じでないと警告されるようなのだ。セキュリティの問題なのかな?よくわからんが、5.3系からの仕様らしい。

php.ini 内に

date.timezone = Asia/Tokyo

という記述を加えれば解決するらしいのだが、ここで困った問題が。

configure した時、特に --with-config-file-path は指定していないので、出来上がった php は /usr/local/lib/php.ini を参照するはずである。
なのに、phpinfo で表示されている Configuration File (php.ini) Path は /usr/local/php/lib を指しているのである。

/usr/local/lib/php.ini に date.timezone の記述を追加し、httpd を再起動しても状況変わらず。だからといって、/usr/local/php/lib/php.ini に同じものを置いても、やっぱり状況変わらずなのだ。どうにも php.ini の内容が反映していない様子。(ちなみに、ブラウザのキャッシュが・・・というような素人じみた落ちは無い(^^;)

何度か --with-config-file-path オプションをつけて再インストールしてみたのだが、何か php 動かなくなっちゃったし(^^;
make clean してやり直していたのだが、make clean した後でソース展開したディレクトリも消して、ソースを展開するところからやり直せばよかったのかな・・・
どうも、make clean だけではさっぱりきれいにならないようである。

結局、解決策は、

5.2系をインストールする

・・・である(^^;

元々ユーザー要件としては「PHP 5.2 のインストール」となっていたので、その最新の 5.2.17 をインストールした。
5.2系は良いなあ。
Default timezone と php.ini で設定している timezone が同じでなくとも、ワーニングなんか吐かない。
そして、php.ini に date.timezone の記述を追加して httpd を再起動すれば、phpinfo の date.timezone directive に関する情報も、すぐに Asia/Tokyo に変更された。

う~ん・・・何か、もっと configure の時に色々とオプションが必要だったんかなあ?

ま、今回は 5.2.17 でまったく問題無いんだけど、今後のことを考えると、5.3系で上手くいかなった理等を調べておきたかったな。

ま、もう、今日は駄目です(^^;

今から岩国まで帰れるかなあ・・・

いや、まあ、もう「汎用データベースモジュール」は使わないことにしたので、どうでも良いっちゃ良いんだけど、この間"GDモジュールが「画像の読み書きをサポートしてない」と言われるのだが"というエントリーに書いたように、PHP でちゃんと gd モジュールのセットアップをしても、

gdモジュールがGIF/JPEG/PNG画像の読み書きをサポートしていません。このモジュールで画像を処理するには、gdモジュールがGIF/JPEG/PNG画像の読み書きをサポートする必要があります。

と「汎用データベースモジュール」の管理画面で怒られちゃう件。

今日、たまたまソースを見てみると、このエラーを出しているところは、admin/index.php の

    if (!$gd_infos['GIF Read Support'] || !$gd_infos['GIF Create Support'] || !$gd_infos['JPG Support'] || !$gd_infos['PNG Support']) {
        $errors[] = constant('_AM_' . $affix . '_GD_NOT_SUPPORTED_ERR');
    }

この部分だった。

「JPG Support」なんて添字の gd 情報をチェックしているよ。
それは、古いバージョンの PHP が戻してくる値でしょうが。今のバージョンだと、「JPEG Support」って項目名なんすけど。

こんなしょうもないことのために、どれだけ PHP の再インストールをしたことか(^^;。俺の貴重な時間を返せ。(ま、その時、自分の PHP のインストール手順ではなく、すぐにソースを疑えばよかったんだけどね(^^;)

つーことで、「坊主憎けりゃ袈裟まで憎い」ではないが、ますます XOOPS が嫌いになった俺なのであった。

いやぁ、ちょっとハマって無駄な時間を過ごした。(^^;

例えば、db_user と db_shop というディレクトリ名で、XOOPS 汎用データベースモジュールを元にした外部モジュールをアップしてインストールをしようとすると、どちらの外部モジュールも一覧に同じ名前で表示されてしまうのだ。

modinfo.php の中で、db_user は「ユーザ検索」、db_shop は「お店検索」と名前を付けているのに、どちらも「ユーザ検索」と表示されてしまう・・・という具合だ。

結局、問題なのは db_user と db_shop というディレクトリ名であった。

XOOPS 汎用データベースモジュールは、ディレクトリ名を変えれば複数設置出来るようになっているのだが、そのため、モジュール名に添字(affix)を付けてモジュールを区別出来るようにしているみたい。

その添字の作り方が

$affix = strtoupper(strlen($dirname) >= 3 ? substr($dirname, 0, 3) : $dirname);

という具合にディレクトリ名の頭 3文字だけを取っているのが問題のようである。

ということで、db1_user、db2_shop のように先頭 3文字を抜いても問題の無いディレクトリ名にしてやれば問題ないのであった。

なんか、もう、いちいちこういう細かい仕様で引っかかって、全然本来の開発のところにたどり付けんな。

複数のプログラマ仲間が「今更 XOOPS?PHP のバージョンアップにもまともに対応出来てないのに?XOOPS に手を出すなんて 3~4年遅いよ。」と言うてたのは本当だな。今更 XOOPS なのである(^^;

このアーカイブについて

このページには、過去に書かれたブログ記事のうちPHPカテゴリに属しているものが含まれています。

前のカテゴリはPerlです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら