カテゴリー: Development

ユーザ定義エラーハンドラの拡張パッチ

最近のPHPはE_ERROR(未定義の関数呼び出しなどで発生)をユーザ定義エラーハンドラで処理できません。これはE_ERRORが発生した場合、必ずeixtを呼び出しスクリプトの実行を停止しないと誤作動する問題に対処した為です。

随分前(PHP 4.3がリリースされた頃)からこんな感じでパッチを書けばよいです、と紹介はしていたのですがWikiに書きました。よろしければご利用ください。ユーザ定義エラーハンドラに問題(E_ERRORが発生する等)が無ければE_ERRORでexitすれば問題は発生しないはずです。万が一、関数名をタイポしていてもエラーページを表示しwebmasterに通知する処理などをエラーハンドラに定義できるので有用です。

php内部でのmmapの使い方

遅ればせながらPHP 5.0.5使っていて直しているだろう、と思い込んでいたバグが直っていない事に気が付きました。

PHP内部のphp_stream_passthru()関数はreadfile()やfpassthru()関数に利用されているのですがmmapの使い方がいい加減です。PHP 4.3.xのバグレポートでreadfile()で大きなファイルが読めない旨のバグレポートがあったので全てのブランチで直っている、と思っていたのが間違いでした。

mmapは名前通りファイルをメモリにマップする関数です。メモリマップすることにより典型的なファイルI/Oコードに必要なバッファへのコピー、その後の出力、というステップがメモリからの読み出しと同時に出力、とバッファコピーが減るメリットがあります。

メモリにマップするので色々制限があります。特に32bitシステムでは小さいファイルしか(と言っても2GBくらいのファイルなら取り扱えますが)取り扱えない、メモリ圧迫する(2GBのファイルをマップすると、2GB mallocが失敗するなど)の問題があります。さらに比較的大きなファイルを実際に読み出すとスワップの嵐になるシステムも… 当たり前といえば当たり前の制限です。

と前置きしたのでPHP 5.0.5でどうなっていたかと言うと「mmapをサポートするシステムの場合、ファイル全体をマップする」ようになっています。当然前述のような問題が発生します。そこで2MB以上のファイルはmmapできないようにしています…

PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC)
{
SNIP
/* For now, we impose an arbitrary 2MB limit to avoid
* runaway swapping when large files are passed thru. */
if (length > 2 * 1024 * 1024) {
return NULL;
}

別にこれ自体はそれほど悪い事(2MBなどと非常に小さい値にしている事は除いて)ではないのですがこのおかげでphp_stream_mmap_range()を利用する、恐らく、ほとんどの関数で2MB以上のファイルを正しく取り扱えなくなっているようです。

中途半端に使える物は使わない方が良いのでmmapを使わせないようにするには

– PHPのランタイムからはstreamのオプションでmmapを使わないよう全てのスクリプトで設定する(iniオプションが無い!)
– 次のパッチを当ててPHPをリビルドする

等として回避する必要があります。

diff -ur php-5.0.5.orig/main/streams/php_stream_mmap.h php-5.0.5/main/streams/php_stream_mmap.h
— php-5.0.5.orig/main/streams/php_stream_mmap.h 2004-02-20 17:22:12.000000000 +0900
+++ php-5.0.5/main/streams/php_stream_mmap.h 2005-10-23 10:23:56.492890384 +0900
@@ -62,7 +62,7 @@

/* Returns 1 if the stream in its current state can be memory mapped,
* 0 otherwise */
-#define php_stream_mmap_possible(stream) (!php_stream_is_filtered((stream)) && php_stream_mmap_supported((stream)))
+#define php_stream_mmap_possible(stream) 0

BEGIN_EXTERN_C()
PHPAPI char *_php_stream_mmap_range(php_stream *stream, size_t offset, size_t length, php_stream_mmap_operation_t mode, size_t *mapped_len TSRMLS_DC);

きちんと直すの事も簡単(チャンク単位でmap, unmapを繰り返す)なのですがとりあえず情報として…

# この問題、開発者が理解してないかも…

また作りを知らない人が…

「PHP Open_BaseDir Security Restriction Bypass Vulnerability」と言うbug truckのエントリを作っている人がいますね…. 何年も前から何度もソフトウェアのデザイン上の間違いではない事は解説されているのですけどね….

最近のPHPマニュアルには「open_basedir」も「safe_mode」もスクリプトを書く人からの不正なファイルアクセスを防止する為のセキュリティ対策ではない事、完全な(安全な)アクセス制御を行う仕組みでは無いことは明記してあります。
# 「It is architecturally incorrect to try to solve this
# problem at the PHP level」
# http://www.php.net/manual/en/features.safe-mode.php
# 「アーキテクチャ的にはこの問題をPHPレベルで解決しようと
# するのは正しくありまえせんが」と記述してあります。

たとえばPostgreSQLのラージオブジェクト関数を使うとWebサーバがアクセス可能なファイル全てにアクセスできます。SQL文でファイルをロードできる物もあります。外部のライブラリやシステムを利用するプログラムがファイルアクセスを完全に制御できないのは*当たり前*の事なのです。

だからといって「open_base_dir」や「safe_mode」が無意味かというとそうではありません。例えば、プログラムミスによりディレクトリ遷移バグが入ってしまった場合などには「open_base_dir」は非常に役に立ちます。ログを自動チェックするようにしていればサーバが攻撃された際にディレクトリ遷移バグがあることと攻撃されている事が判別することができます。

PostgreSQL 8.1のパフォーマンス

PostgreSQLのパフォーマンスはpostgresql.confに大きく影響されるので、速くなったかどうか判りづらい場合も多いです。しかし、8.1では確実に速くなっているようです。現在8.1はbeta1ですが少しだけ比較してみました。

詳しくはWikiのページを見ていただくとして以下の様にpgbenchで計測すると

./pgbench -v -h 192.168.100.204 -U yohgaki -c 20 -t 200

PostgreSQL 8.0.3

tps = 4683.835265 (excluding connections establishing) (Select only)
tps = 1032.798585 (excluding connections establishing) (Update 省略)
tps = 423.926137 (excluding connections establishing)

PostgreSQL 8.1beta1

tps = 5985.801678 (excluding connections establishing) (Select only)
tps = 1428.605103 (excluding connections establishing)(Update省略)
tps = 533.005286 (excluding connections establishing)

という感じの結果になりました。
postgresql.confの設定は多少チューニングした物を使っています。postgresql.confもWikiのページに添付してあります。

pthread版pgbenchの拡張

実はpthread版pgbenchの作成には別の目的もあります。オリジナル版pgbenchのコードを見ると分かるのですが、非同期クエリを使用しているので送信するクエリのカスタマイズが面倒です。pthread版pgbenchの別の目的、と言うより本来の目的、はpostmasterが書き出したログから自動的にクエリを収集し、再生するベンチマークを簡単に行いたいので作る、と言う事にあります。

今の所こんな感じで実装するつもりです。

postgresql.confのログ設定が

log_line_prefix = ‘%r’
log_statement = true

で出力されたログから自動的に各クライアントのクエリを出力し設定されたスレッド数(クライアント数)でベンチマーク出来るようにする予定です。

今のコードだとログの読み取りとクエリ保存を行えるようにして、各スレッドがクエリを実行するように変更すれば良いだけです。簡単なのでそのうち変更します。

PHP 5.0.5リリース

PHP 5.0.5がリリースされました。XMLRPCのセキュリティフィックスが含まれています。

他のディストリビューションも同じとは思いますが、Momonga LinuxのXMLRPCは現行リリース(5.0.4-6m)でもセキュリティ対策済みです。

pgbenchのpthread版

(やはりバグを発見したので修正)

JPUG広報Blogに「pgbenchのpthread版が欲しい」と書いていましたが、先週末にPHP関西のセミナー講師を引き受けていたのでその移動時間中にテキトーに作ってみました。テキトーに作ったので勘違いしてバグを入れていました。今度はたぶん正しい結果になっていると思います。

サーバ環境
Athlon64 3200/3GB Memory/SATA2 HDD/Momonga Linux x86_64
PostgreSQL 8.0.3(64bit)(全てのSQL文をホスト/ポート付きで記録。他はほぼデフォルト。)

クライアント環境
AthlonXP 2500+/2GB Memory

pthread版pgbench

[yohgaki@dev pgbench]$ time ./pgbench -v -h 192.168.100.204 -U yohgaki -c 10 -t 100
starting vacuum…end.
starting full vacuum…end.
Warming up 15 seconds…
Start benchmarking…
End benchmarking….. (4.96586 seconds)
transaction type: TPC-B (sort of)
scaling factor: 10
number of clients: 10
number of transactions per client: 100
total number of transactions processed: 1000
tps = 235.404176 (excluding connections establishing)

real 0m25.739s
user 0m0.214s
sys 0m0.313s
[yohgaki@dev pgbench]$

こんな感じです。

何だか遅くなってしまたのでコードをもう少し効率化してみました。
今度はオリジナル版よりは速くなりました。

pthread版pgbench

[yohgaki@dev pgbench]$ time ./pgbench -v -h 192.168.100.204 -U yohgaki -c 50 -t 10
starting vacuum…end.
starting full vacuum…end.
Warming up 0 seconds…
Start benchmarking…
End benchmarking….. (1.16363 seconds)
transaction type: TPC-B (sort of)
scaling factor: 1
number of clients: 50
number of transactions per client: 10
total number of transactions processed: 500
tps = 429.689481 (excluding connections establishing)

real 0m2.655s
user 0m0.047s
sys 0m0.088s

オリジナル版

[yohgaki@dev pgbench]$ time pgbench -v -h 192.168.100.204 -U yohgaki -c 50 -t 10
starting vacuum…end.
starting full vacuum…end.
transaction type: TPC-B (sort of)
scaling factor: 1
number of clients: 50
number of transactions per client: 10
number of transactions actually processed: 500/500
tps = 337.674248 (including connections establishing)
tps = 379.093451 (excluding connections establishing)

real 0m1.615s
user 0m0.043s
sys 0m0.210s

と、多少スレッド版の方が速いです。今度は繰り返し実行してみてもスレッド版の方が速い傾向は変わりませんでした(汗

ベンチマークを開始する前にウォーミングアップの時間を設定したかった事、クエリ実行間隔をランダムに設定したかった事もpthread版が欲しかった他の理由でした。そこで

-w ウォームアップ時間(秒)
-r ランダム遅延(マイクロ秒)

も設定できるようにしました。よくあることですがサーバに負荷をかけた直後は良い性能がでるためウォームアップ時間は設定できた方が便利です。

ウォームアップ時間を5秒に設定した場合

[yohgaki@dev pgbench]$ time ./pgbench -v -h 192.168.100.204 -U yohgaki -c 50 -t 10 -w 5
starting vacuum…end.
starting full vacuum…end.
Warming up 5 seconds…
Start benchmarking…
End benchmarking….. (1.48874 seconds)
transaction type: TPC-B (sort of)
scaling factor: 1
number of clients: 50
number of transactions per client: 10
total number of transactions processed: 500
tps = 335.854481 (excluding connections establishing)

real 0m6.671s
user 0m0.124s
sys 0m0.260s

とこの様な感じです。オリジナル版にウォームアップ時間オプションを追加して欲しいな、と書いておいたら石井さんが追加してくれるはず :)

ソースは
http://www.ohgaki.net/wiki/index.php?PostgreSQL%2Fppgbench
からダウンロードできます。変更するかもしれないので日付を入れておきました。日付が入っていないソースは古いソースです。もし古いソースをお持ちの場合、新しいソースを使ってください。古い物にはバグがあります。

PHPのE_STRICTエラー

PHPのエラーレポートレベルはphp.ini設定のerror_reportingで設定されています。

PHP5から追加されたE_STRICTで「あれ」と思われるかもしれない状況があるので書いておきます。

PHP5でE_ALLをerror_reportingに設定してもE_STRICTレベルのエラーは報告されません。デフォルト設定ファイルではE_STRICTは無視されるようになっています。

error_reporting = E_ALL | E_STRICT

と設定しないとより厳しいエラーチェックが行われません。

開発時には言語が用意しているエラーチェックを出来る限り多く使用するべきです。しかし、E_STRICTレベルのエラーレポートを行う設定を行った場合に問題が発生する場合があります。次のコードがどのように処理されるか考えると分かります。

<?php
error_reporting(E_ALL); // E_STRICTは不必要

class foo {
  var $bar;
}
?>

E_STRICTで報告されるエラーには”var”宣言されたプロパティにpublic/private/protectedを使用するよう推奨するエラーがあります。このエラーはコンパイル時に発生するため、スクリプト中でerror_reporting関数を使ってエラー報告レベルと変更してもE_STRICTエラーを無視できません。E_STRICTエラーが有効な環境で、error_reporting関数で確実にE_STRICTエラーが発生しないようにするには、E_STRICTエラー出力を抑制するには最初に読み込まれるファイルのコード中にE_STRICTエラーが発生しないしerror_reporting関数を使用してエラー報告レベルを変更しなければなりません。

# E_STRICTは開発時だけ使う、という方針がお勧めです。
# PHP4用に作ったアプリの修正は手間な場合は、INSTALL
# ファイルなどにE_STRICTは無効にするよう書くだけでも
# 良いかもしれません。

備考:
E_NOTICEレベルのエラーは全て実行時に発生するエラーであるため、E_STRICTの様な問題は発生しません。念のため。

追記:
今時のPHPアプリケーションならE_STRICTエラーも発生しないようにプログラムを作成すべきす。

 

関数の戻り値と定数値(リテラル)への参照

追記:このエントリへのアクセスが多いので加筆修正しました。

Fatal error: Only variables can be passed by reference

直訳すると「致命的エラー:変数のみ参照渡しが可能です」となります。エラーメッセージの通りvariable(以外)の値は参照として渡せないのでエラーになっています。エラーメッセージが適切かどうかは微妙ですが、意訳すると「致命的エラー:ソースコード中に記述した定数値(リテラル)へのアクセスはできません」あたりが妥当と思います。当然ですがdefineで定義した定数値を返す事は可能です。PHP内部では定数は変更できない「変数」の様に実装されているからです。このエントリの「定数値」を正確に書くと「ソースコード中に記述された定数値」となります。

もっと読む

QRコードを短冊に

メモ。QRコードに関するblog。本文もQRコードならコメントもQRコードです(気付くのが遅すぎ?

とろこでトップページの「QRコード読み取りのコツ」に

■QRコードの真正面から撮影

とありますが、真正面から読まないとQRコードが読み取れないリーダ(携帯)があるのですね。と、書いている自分も正面から読み取るようにしていますが、QRコードは印刷面が平たければ、ななめから読み取っても読み取れる設計になっています。QRコードの仕様を知らない方も多いと思うので簡単な説明を付けておきます。隅の大きめの■が斜めからも読み取れるようにするための役割を持っています。全ての隅に大きめの■が無いのは読み取り開始位置を判別できるようにするためです。カメラの解像度やQRコードが写されている領域の影響もあるので正面から撮らないと読み取りに失敗する確立は高くはなると思います。エラー補正情報をQRコード内にたくさん入れていれば読み取りに成功する確立は高くなりますが、QRコードが大きくなります。微妙ですね。

allow_url_fopen

追記:
現在のPHPではリモートファイル読み込みを制御するphp.ini設定としてallow_url_fopen(URL等のファイルとして読み込むフラグ)とallow_url_include(URLなどをPHPスクリプトとして読み込むフラグ)があります。php://input(標準入力用のURL。Webアプリの場合、POSTリクエストなどが読み込める)もallow_url_include=Offでは利用できません。このためallow_url_include=Offの場合、リモートスクリプトからの読み込みを防止できます。

基本的には

  • allow_url_includeは常に無効(JSONなどでなくPHPスクリプトとしてリモートデータを読む、などの場合は局所的に有効化)
  • allow_url_fopenは全く必要ないなら無効

とすると良いでしょう。

PHPを使っている方はHTTP/FTP/SSH等のプロトコルでリモートサーバ上のファイルをローカルファイルの様に読み書きできる事をご存知と思います。この機能はphp.ini設定のallow_url_fopenディレクティブで有効/無効を設定できるようになっています。PHP 4.3.4より前のPHPではこの機能のスクリプト中からも無効/有効に設定を変更する事ができました。(INI_ALLの設定項目であった)

驚いたことにPHP 4.3.4からphp.iniからしかこの設定を変更できなくなってしまいました。(INI_SYSTEMの設定項目になった)誰かがセキュリティ強化を目的として変更したのだとは思いますが、セキュリティも強化できず、有用なリモートファイルアクセス機能も使えなくする非常に拙い変更です。

例えば、phpBB(BBSアプリケーション)ではinclude/require文に不適切に処理されたユーザ入力が利用されている為、リモートスクリプトを読み込み実行できてしまう非常に深刻なセキュリティ上の問題がまた最近見つかりました。phpBBはallow_url_fopen機能が無効であっても動作するので

allow_url_fopen = Off

と設定するか必ず読み込まれる設定ファイルで

ini_set(‘allow_url_fopen’, 0);

とすると、phpBBのようなアプリケーションでも比較的安全に運用することができました。

しかし、allow_url_fopenがINI_SYSTEMの設定項目になった為、前者の方法を取ると他のアプリケーションで、場合によっては非常に有用な、allow_url_fopen機能を使えなくなってしまいました。後者の方法は、特定のアプリケーションのみの設定を変更するのに有効ですが、INI_SYSTEM設定項目であるため実際には無効に設定できなくなってしまいました。

セキュリティ上の意味は容易に理解できるであろうと、internals@list.php.net にallow_url_fopenの設定を

デフォルトOFF
INI_ALLへ変更

するように提案して見たところ議論が結構荒れています…
この設定が安全かつ不必要な機能制限が無く、最も良い設定と思うのですが…

# allow_url_fopen_includeのようにinclude/require文用の設定
# を追加するのも良いですが、デフォルトOFF、INI_ALLであるべき
# と思います。

php-rast

Rastとはネットワーク応用通信研究所が開発している全文検索システムです。

本ソフトウェアは,あらかじめ対象となる文書群から検索に必要な情報を格納するデータベースを作成しておき,それに対して検索を行う全文検索システムです.

検索方式は N-gram 方式や分かち書き方式から選べます.また,必要に応じて文字列処理モジュールを差し替えることができます.

なお,本ソフトウェアは IPA の平成16年度オープンソフトウェア活用基盤整備事業の委託を受けて開発を行っています.

このRast用のPHPモジュールを冨田冨田隆三さんが公開されています。

名古屋市立大学の冨田です

以前、全文検索エンジンRast のモジュールを公開したところ、ここでライセンス違反の可能性を指摘されて公開を止めていましたが、Rast-0.2.0 で BSD ライクな緩いライセンスに変更されたようなのでまた公開してみます。

ダウンロードはこちらからどうぞ。
http://a157.debian.co.jp/php_rast/

冨田

サンプルの動作は良い感じです。サンプルコードもざっと見てみましたが使いやすそうです。

_php_stream_passthru

php-usersのMLに投稿した内容の補足です。コードはPHP 4.4の開発ブランチのソースです。

main/stream.cに_php_stream_passthru関数が定義されています。reafile関数(ファイルの中身を全て出力)、fpassthru関数(ファイルリソースの中身を全て出力)に利用されています。

PHPAPI size_t _php_stream_passthru(php_stream * stream STREAMS_DC TSRMLS_DC)
{
    size_t bcount = 0;
    int ready = 0;
    char buf[8192];
#ifdef HAVE_MMAP
    int fd;
#endif

#ifdef HAVE_MMAP
    if (!php_stream_is(stream, PHP_STREAM_IS_SOCKET)
            && stream->filterhead == NULL
            && php_stream_tell(stream) == 0
            && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD, (void*)&fd, 0))
    {
        struct stat sbuf;
        off_t off;
        void *p;
        size_t len;

        fstat(fd, &sbuf);

        if (sbuf.st_size > sizeof(buf)) {
            off = php_stream_tell(stream);
            len = sbuf.st_size - off;
            p = mmap(0, len, PROT_READ, MAP_SHARED, fd, off);
            if (p != (void *) MAP_FAILED) {
                BG(mmap_file) = p;
                BG(mmap_len) = len;
                PHPWRITE(p, len);
                BG(mmap_file) = NULL;
                munmap(p, len);
                bcount += len;
                ready = 1;
            }
        }
    }
#endif
    if(!ready) {
        int b;

        while ((b = php_stream_read(stream, buf, sizeof(buf))) > 0) {
            PHPWRITE(buf, b);
            bcount += b;
        }
    }
    return bcount;
}

注目すべきは以下です。

            if (p != (void *) MAP_FAILED) {
                BG(mmap_file) = p;
                BG(mmap_len) = len;
                PHPWRITE(p, len);
                BG(mmap_file) = NULL;
                munmap(p, len);
                bcount += len;
                ready = 1;
            }

PHPWRITEマクロは最終的に出力バッファに書き出します。PHPからの出力は最終的にWebサーバにバッファされる場合があります。つまり、一度に大量のデータを出力するとメモリを大量に必要とする可能性があります。

Momoery Mapped I/Oの利点がバッファ無しでデータを読める事は分りますが、大きなファイルを送信するには不適切な事は明らかです。データを適切なチャンクサイズに区切ってPHPWRITEに書き込むよう変更しなければならないですね…

DokuWiki

久しぶりにmadwifiの設定をしようとmadwifiのページを見てみると見慣れないWikiを使っていたのでどんなWikiかさらっと見てみました。インストールやソースを読んでいないので見てみた感想です。

基本的なWiki機能はそろっているようです。ページの場所 “top>a page>another page”の様に表示されるのも便利です。ログインユーザ登録もサポートしているようで、Eメールアドレスを登録してから編集を許可する、という運用ができるのはSPAM対策やセキュリティ対策に役立つと思います。

次のような機能を持っているようです。

DokuWiki Features here

* works on plain text files, no database needed
* simple syntax and easy editing with quickbuttons and accesskeys
* Section Editing allows you to edit small parts of a page
* automatic generation of content tables
* unlimited page revisions
* colored side by side diff support
* support for read only pages
* syndication of recent changes as RSS Feed
* namespaces
* Interwiki Links
* uploading and embedding images
* image caching and resizing
* easy navigation through breadcrumbs
* Customizing with templates and plugins
* Multilanguage Support
* Spam blacklist
* custom text replacements
* pagecaching
* locking to avoid edit conflicts
* full UTF-8 support
* and more

Wiki機能の比較は見るだけでも興味深いと思います。

Tipsのページを見てみると色々な機能が追加できる事が分かります。SVGをPNGやGIFに変換、ページをPostscriptに変換、HTMLからDokuWiki形式への変換方法が記載されています。

面白かったのはNanoWebをサポートするWebサーバとして記載されている所です。NanoWebはPHPで記述されたWebサーバで

Nanoweb’s main features are :

– HTTP/1.1 compliance
– Powerful and easy configuration
– Modular architecture
– FastCGI, CGI and Server side includes support
– Name and port based virtual hosts
– Access control lists
– htpasswd, MySQL, PostgreSQL and LDAP authentication support
– Themes for server generated content
– Apache compatible log format, MySQL logging
– Directory browsing
– inetd support and SSL via external helpers
– Denial of Service protection
– Proxy Server extension
– Filters and gzip support
– RBL support (mail-abuse.org)
– Extension Protocols (request methods) support
– … and a lot more

と色々盛り沢山です。

コマンドラインのPHPさえインストールされていれば自分でWebサーバを立てる事ができます。NanoWebのソースは以前に読んだ事があるので多少は分かります。pluginの作成は簡単そうでした。速度的にも普通(?)のリクエスト数であれば十分処理できるパフォーマンスでした。(思ったより速くて驚いたと思います)

PHP4でpublic

PHP本家の開発ML internals@lists.php.net ではPHP4でpublic宣言を行えるようにするかどうかで盛り上がっています。

PHP5を使っている方はご存知の通り、PHP5からオブジェクトのプロパティはpublic, protected, privateにアクセスレベルを限定できるようになりました。それと同時に古いプロパティ宣言であるvar宣言は使わないよう推奨されています。

初めの頃のPHP5のリリースではPHP5で追加されたE_STRICTエラーを表示する為の記述に間違いがありました。E_ALLではE_STRICTエラーでは表示されず、E_ALL | E_STRICTにしなければなりません。E_STRICTエラーにはvar宣言についてもvarではなくpublic, private, protectedを使用する旨のエラーが発生します。E_STRICTエラーを表示する設定方法に間違いがあったため、E_STRICTエラーには気が付きづらかったと思います。E_STRICTレベルエラーを有効にしてエラーの数に驚いた方も多いかも知れません。

しかし、var宣言エラーの問題さえクリアすればほとんどE_STRICTレベルのエラーを回避し、PHP4とPHP5の両方で実行できるコードを書くことも可能になります。現状ではPHP4ではクラス定義の際、プロパティは必ずvar宣言しなければならないのでクラスを使えばE_STRICTエラーは必ず発生します。

class foo {
public $var;
}

をPHP4でも使えるようにするメリットはあります。PHP4用のコードと言いつつPHP4.4より古いPHP4では実行できなくなるのも困るというのも分かります。

私はPHP4の文法は拡張せず最初に読み込むアプリケーションの設定ファイルなどで


error_reporting(E_ALL);

を実行する方がよいのではないかと思っています。
この方法には最初に読み込まれるファイルが在ること、そのファイルにクラス定義が含まれないと前提条件もありますがこれでも十分ではないかと思います。

# 最悪、auto_prependでerror_reporing設定を変える方法も使えます。