PHPの最近のブログ記事

CentOS 5.3、PHP5.1.6な環境でPECLでImagickをインストールしようとしたら下記のようなエラーが出た。
# pecl install imagick
downloading imagick-3.0.0.tgz ...
Starting to download imagick-3.0.0.tgz (93,488 bytes)
.....................done: 93,488 bytes
13 source files, building
running: phpize
Configuring for:
PHP Api Version:         20041225
Zend Module Api No:      20050922
Zend Extension Api No:   220051025
Please provide the prefix of Imagemagick installation [autodetect] :
building in /var/tmp/pear-build-root/imagick-3.0.0
running: /tmp/tmpGia3gn/imagick-3.0.0/configure --with-imagick
checking for egrep... grep -E
checking for a sed that does not truncate output... /bin/sed
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables...
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
checking whether gcc and cc understand -c and -o together... yes
checking if compiler supports -R... no
checking if compiler supports -Wl,-rpath,... yes
checking build system type... i686-redhat-linux-gnu
checking host system type... i686-redhat-linux-gnu
checking target system type... i686-redhat-linux-gnu
checking for PHP prefix... /usr
checking for PHP includes... -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext
checking for PHP extension directory... /usr/lib/php/modules
checking for PHP installed headers prefix... /usr/include/php
checking for re2c... re2c
checking for re2c version... 0.13.5 (ok)
checking for gawk... gawk
checking whether to enable the imagick extension... yes, shared
checking whether to enable the imagick GraphicsMagick backend... no
checking ImageMagick MagickWand API configuration program... found in /usr/bin/Wand-config
checking if ImageMagick version is at least 6.2.4... found version 6.2.8
checking for magick-wand.h header file... found in /usr/include/wand/magick-wand.h

checking PHP version is at least 5.1.3... /tmp/tmpGia3gn/imagick-3.0.0/configure: line 3339: test:
 Usage: /usr/bin/php-config [--prefix|--includes|--ldflags|--libs|--extension-dir|--include-dir|--php-binary|--version]: integer expression expected
configure: error: no. found 5.1.6
ERROR: `/tmp/tmpGia3gn/imagick-3.0.0/configure --with-imagick' failed


エラーメッセージでGoogle検索しても全然事例が見つからない。
大パニック。(><)

ふと、PHP公式サイトのimagickインストールの項を見ていたらヒントがあった。
http://www.php.net/manual/ja/imagick.installation.php
vbsaltydog 31-Jul-2010 03:31 I could not install via PECL or compiling from source because of an error from line 3339 of the configure file generated by phpize so I looked at the configure file at line 3339 and it was just a check for the PHP version using the php-config command with the --vernum switch which was not supported by my PHP version so I commented out that check from the configure file and then it would configure, compile, and install. After installation, it put the shared object file in my php extension modules directory so I added an entry to my /etc/php.d directory to load the extension file and restarted apache and the imagick section is present in my info.php output.
imagickのインストーラがPHPのバージョン確認しようとして、その"php-config --vernum"コマンドがこけているというのだ。

imagickのバグ?peclのバグ? はたまたphpizeのバグ?・・・一瞬途方にくれた。

しかしよく見ると、手動configure & コンパイルすればいけたと書いてあるのでやってみる。

まず、PECLのサイトでソースパッケージを探す。
http://pecl.php.net/package/imagick
展開する
# wget http://pecl.php.net/get/imagick-3.0.0.tgz
# tar xvfz imagick-3.0.0.tgz
# cd imagick-3.0.0

ここでおもむろに、
# ./configure
んー何も起こらん。

# pecl install .
これもダメ

# pecl install ../package.xml
ERROR: file ../examples/polygon.php does not exist
お、一歩前進。

# cp ../package.xml
# pecl install package.xml
をを、インストーラが起動した。
最初と同じエラーが出た。

これでめでたくディレクトリ内にconfigureファイルが生成された。
# cat configure -n

  3325
  3326    if test -z "${PHP_VERSION_ID}"; then
  3327      if test -z "${PHP_CONFIG}"; then
  3328        { { echo "$as_me:$LINENO: error: php-config not found" >&5
  3329  echo "$as_me: error: php-config not found" >&2;}
  3330     { (exit 1); exit 1; }; }
  3331      fi
  3332      PHP_IMAGICK_FOUND_VERNUM=`${PHP_CONFIG} --vernum`;
  3333      PHP_IMAGICK_FOUND_VERSION=`${PHP_CONFIG} --version`
  3334    else
  3335      PHP_IMAGICK_FOUND_VERNUM="${PHP_VERSION_ID}"
  3336      PHP_IMAGICK_FOUND_VERSION="${PHP_VERSION}"
  3337    fi
  3338
  3339    if test "$PHP_IMAGICK_FOUND_VERNUM" -ge "50103"; then
  3340      echo "$as_me:$LINENO: result: yes. found $PHP_IMAGICK_FOUND_VERSION" >&5
  3341  echo "${ECHO_T}yes. found $PHP_IMAGICK_FOUND_VERSION" >&6
  3342    else
  3343      { { echo "$as_me:$LINENO: error: no. found $PHP_IMAGICK_FOUND_VERSION" >&5
  3344  echo "$as_me: error: no. found $PHP_IMAGICK_FOUND_VERSION" >&2;}
  3345     { (exit 1); exit 1; }; }
  3346    fi
  3347
3339行目あたりに注目。
確かに、PHPのバージョンを確認するのに"php-config --vernum"のようなコマンドを実行している。

試しに、手動でコマンドを実行してみる。
# php-config --vernum
Usage: /usr/bin/php-config [--prefix|--includes|--ldflags|--libs|--extension-dir|--include-dir|--php-binary|--version]
をを、最初のエラーと同じようなエラーが出た。

なるほどこれが原因か。
「php-config --vernumでバージョン番号を取得しようとしているが、--vernumオプションは存在しない。よってconfigureがコケる。」

Imagickのバグか、PECLのバグか、phpizeのバグか、php-configのバグか、どれが真の原因なのかはわからないが、とりあえず修正することはできそうだ。

とりあえず安直php-configを修正することにする。
$ which php-config
/usr/bin/php-config
$ nano /usr/bin/php-config

#! /bin/sh

prefix="/usr"
exec_prefix="/usr"
version="5.1.6"
vernum="50106"
includedir="/usr/include/php"
includes="-I$includedir -I$includedir/main -I$includedir/TSRM -I$includedir/Zend -I$includedir/ext"
ldflags=" -L/usr/kerberos/lib"
libs="-lcrypt   -lcrypt -laspell -lpspell -lgmp -ldb-4.3 -lcurl -lbz2 -lz -lpcre -lresolv -lm -ldl -lnsl  -lxml2 -lz -lm -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lss$
extension_dir='/usr/lib/php/modules'
program_prefix=""
program_suffix=""
exe_extension=""
php_binary="/usr/bin/${program_prefix}php${program_suffix}${exe_extension}"

case "$1" in
--prefix)
        echo $prefix;;
--includes)
        echo $includes;;
--ldflags)
        echo $ldflags;;
--libs)
        echo $libs;;
--extension-dir)
        echo $extension_dir;;
--include-dir)
        echo $includedir;;
--php-binary)
        echo $php_binary;;
--version)
        echo $version;;
--vernum)
        echo $vernum;;
*)
        echo "Usage: $0 [--prefix|--includes|--ldflags|--libs|--extension-dir|--include-dir|--php-binary|--version]"
        exit 1;;
esac

exit 0
編集したら実行
# php-config --vernum
50106
成功!

そして再度imagickをインストール。
# pecl install imagick
うまく行った!
あとはphp.iniに
extension=imagick.so
を書けばOK!

あ~解決できてよかった。。。

その悲劇は、PHPの巨大なクラスをリファクタリングしたのが原因で起こりました。


「フォームの送信ボタンを連打すると発生するとDB上で2重登録されてしまうバグがあり、その問題に対処するために確認画面に遷移したときに重複レコードを削除することになっているはずが削除されない」というものでした。


リファクタリング前のクラス


class myClass {
...
function doSomething($user_id)
{
$sql1 = "SELECT * FROM tb1 WHERE user_id = " . $user_id;
....
$sql2 = "DELETE FROM tbl1 WHERE user_id = " . $user_id;
}
...
}


リファクタリング後のクラス(バグ有り)

class myClass { 
 ...

function doSomething()
{
$sql1 = "SELECT * FROM tb1 WHERE user_id = " . $this->gerUserId();
....
$sql2 = "DELETE FROM tbl1 WHERE user_id = " . $user_id;
}
...
}


いわゆる「問い合わせによる一時変数の置き換え」をやろうとして、置換が漏れてました。

($user_id を $this->getUserId()に置き換えたかった)

しかもこのバグを本番にアップして2ヶ月間も気づかず放置。

上記のDELETE文はSQL文法エラーで実行されず、消さなきゃいけないデータが2ヶ月も消えないまま残ってしまっていた。。。


敗因


最初に頭によぎったことは、「Perlで書いてれば!!Perlなら絶対use strictって書くからこんなミスしないのに!!」
こともあろうに私は言語のせいにしようとしました。

もちろんPHPに非があろうはずがありません。
悪いのは私であって、言語ではありません。


E_STRICTを有効にしてなかった

Perlのuse strict;を羨むくらいなら、E_STRICTを有効にしておけばよかった。


自動単体テストを書いていなかった

リファクタリングには自動単体テストが必須なわけですが、私はこれを怠けたのです。

「それってリファクタリングちゃうやん」と言われたら、まったくその通りです。


手動テストをしていなかった

上記delete文がちゃんと機能しているかを確認する手動テストすらしていませんでした。
典型的なEdit & Pray(編集して祈る)開発スタイル !!


本番サーバでのエラーログを見てなかった

上記スクリプトはSQL的に文法エラーなわけで、当然サーバのエラーログにもエラーが残っていました。
しかしその文法エラーのエラー文を見ても、上記スクリプトが原因だと気づきませんでした。。。


ユーザからの声に気づけず

「動作がおかしい」という話をここ数週間聞いてたのですが、どうしてもバグが再現しないので「バグじゃないかもしれない」などと甘いことを考えていました。

本気でバグを探そうという気概が足りなかったのかもしれません。


心がまえ

「自分はリファクタリングに慣れてるからテストなんか書かなくても大丈夫」という慢心がありました。

この慢心がすべての原因のような気がします。(←これが言いたかった)


/**
 * 半角数字→全角数字に置き換えるmodifier
 *
 * @see
 * http://pentan.info/php/smarty/mod_hkana.html
 *
 */
function smarty_modifier_numeric_hantozen($string, $encoding = 'UTF-8')
{
    return mb_convert_kana($string, "N", $encoding);
}

使い方

ファイル名を "modifier.numeric_hantozen.php" にして、Smartyのプラグインディレクトリに保存してください。

テンプレート内で、下記のようにと書くと変換してくれます。

{$number|numeric_hantozen}

参考記事
携帯表示用に文字を全角から半角にする - [Smarty] ぺんたん info

date('Y-m-d h:m:s')の結果が12時間ずれる!?

date関数を使うと12時間ずれることがあります。

例えば、現在時が"2010-05-29 17:00:00"のとき、
$ php -r "echo date('Y-m-d h:m:s');"  

2010-05-29 05:00:00

落ち着いて!
自分の書いたコードをよく見て!

原因は、"h:m:s"の書き方が間違っているからです。
正しくは "H:m:s" です!

$ php -r "echo date('Y-m-d H:m:s');"  

2010-05-29 17:00:00

あ~よかった。。。
マニュアルをちゃんと読みましょう。
http://jp.php.net/manual/ja/function.date.php

Lime.phpの最新版のソースコードをダウンロードする方法

Limeというのは、PHPで単体テストを書くためのライブラリです。
ライブラリといってもただのクラスファイルで、lime.phpの1ファイルをインクルードするだけですぐ使えます。
「軽量・シンプル・かんたん」が好きなあなたにはぴったりです。

さてこのlime.phpの唯一の難点、それはどこからダウンロードすればいいのか分かりにくいこと。

すばり、場所はここです、ここ!(ver 1.0.9)
↓↓
http://trac.symfony-project.org/browser/tools/lime/tags/RELEASE_1_0_9/lib/lime.php

バージョンを選ぶならこちら
↓↓
http://trac.symfony-project.org/browser/tools/lime/tags

最新の安定版をダウンロードして使いましょう。
2010.5月現在も、安定版の開発は続いているようです。

このアーカイブについて

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

前のカテゴリはPerl再入門です。

次のカテゴリはPowerPointです。

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

Powered by Movable Type 5.02