レンタルサーバーで PEL が動かない問題
以前の記事で PEL を利用した PHP による EXIF 読み込みを取り上げた。
動作は Windows Vista + Eclipse PDT で確認。また開発中の WordPress プラグインにもこの時の実装を元にした処理が組み込まれており XAMPP 上のプラグイン実行でも該当処理は問題なし。
しかし今日、プラグインをリリースするためレンタル サーバーに設置した本ブログでテストしたら EXIF 読み込みが動作しない。どうやら PEL の 処理が Fatal Error になるようだ。プラグインでは PEL による EXIF 読み込み部分を独立した CGI として設計しているため全体への影響はないが、かなり痛い問題である。
既に原因は判明しており対策を検討中だが PEL を利用したいと考えている人の役に立つかもしれないので、この問題の調査方法と原因をまとめておく。
調査方法
はじめに問題の再現する最小コードを作成。EXIF 読み込みが怪しいという目星は付いていたので、処理の各ステップと Fatal Error を echo
で出力してみる。
<?php
// Fatal Error 用
register_shutdown_function( "shutdownHandler" );
function shutdownHandler()
{
$error = error_get_last();
if( $error[ "type" ] == E_ERROR )
{
echo $error[ "message" ];
}
}
// スクリプト読み込み用
$include = include_once( "pel-0.9.1/PelJpeg.php" );
echo( $include ? "include_once [{$include}]" : "Error : include_once" );
// PEL 用
try
{
$url = "/blog/2009/11/29.JPG";
echo( class_exists( PelJpeg ) ? "class_exists( PelJpeg )" : "Error : class_exists( PelJpeg )" );
$jpeg = new PelJpeg( $url );
echo( "PelJpeg(url)" );
}
catch( Exception $e )
{
echo( "Error : PelJpeg(url)" );
}
?>
PelJpeg
のインスタンス生成まで成功すれば PEL 本体ではなく利用方法に問題があると切り分けられるだろう。これを test.php としてサーバーに配置して Web ブラウザーからアクセスしてみたところ以下のような結果が出力された。実際に出力されるテキストは詰まっているが、分かりやすくするため改行を入れている。
include_once [1]
class_exists( PelJpeg )
Call to undefined function unixtojd()
まず 1 ~ 2 行目の内容から include_once
には成功して PelJpeg
も定義されていることがわかる。しかし 3 行目に見慣れないエラーが。自前のメッセージではないため、これは Fatal Error であろう。そしてエラーは unixtojd
という未定義の関数呼び出しを問題としている。
原因
問題の unixtojd
とはカレンダー関数である。
カレンダー関数の説明を読むと使用条件が以下のように書かれている。
これらの関数を動作させるには、 --enable-calendar を指定して PHP をコンパイルする必要があります。 Windows 版の PHP にはこの拡張モジュールのサポートが組み込まれています。これらの関数を使用するために拡張モジュールを追加でロードする必要はありません。
- 2018/11/27
- この引用文は記事を書いた当時、students.kiv.zcu.cz に掲載されていたもの
- このページは消滅しているので jp2.php.net に変更。
この説明で合点がいった。
本記事の冒頭でも触れたように PEL を試した環境はすべて Windows の XAMPP。つまりカレンダー関数は始めから用意されていた。しかし他の環境では説明どおりに PHP をコンパイルする、またはカレンダー モジュールを導入して php.ini を書き換えなければならない。
私が利用しているレンタル サーバーはさくらインターネットのスタンダード コースだが、恐らくは他社のサービスでも発生するだろう。対策方法がサーバーの PHP をいじるしかなくて困った。プラグインにカレンダー系モジュールを同梱して side-by-side に実行する方法はないものだろうか?