私の管理しているサイトで利用している、PHPのテンプレートクラス(PHP4テンプレートクラスライブラリ)が、サーバ移行でPHPのバージョンが上がったためか、Noticeを吐くようになったので、対処したメモ。もしかしたら、参考になる人もいるかもしれないので、公開します。
上記のテンプレートクラスについて簡単に書いておくと、PHP上でテンプレート的なものを簡単に実現してくれる仕組み。PerlでいうHTML::Templateに似てます。
かなり規模の小さいページであっても、ロジックとビューは切り離した方が、メンテナンスする際には便利。というわけで、上記のライブラリは大変便利に利用させて頂いております。
今回の問題は、サーバを更新した際に起こりました。PHPのバージョンが変わったことに起因していると思います。もしかしたら設定で変えられる範囲内かもしれないけど、そこまでは見ていません。
- 移行前の環境: Ubuntu8.04LTS(PHP 5.2.4-2ubuntu5.27)
- 移行後の環境: Ubuntu12.04LTS(PHP 5.3.10-1ubuntu3.6)
PHP Notice: Undefined offset: n in /var/www/virtualhosts/domain/tmpl2.class.inc on line nnn
Noticeは画面には出ないみたいで、気づかない場合も多いでしょう。コマンドライン(php-cli)で動かしたりすると見えます。これも設定次第でしょうが。
そのライブラリのソースを見てみると、一番分かりやすいのがこの部分。
for ( $j = 0 ; $loopbuf[$j] ; $j++ )
CとかJavaで育った人は、おそらくこういうコードは書かない(範囲外で例外が飛んだりするし)と思うのですが、PHPでこれまで何も問題なく動いていたということは、PHPの文化として許容範囲のコードだったのでしょう。かつては。
私が知る限り、PHP4の時代から、後方互換性についてはあんまり意識されていないメンテナンスが多かったように思います。もちろんプログラミング言語なんて、多かれ少なかれそういう物なのですが、「ちょっとそこを変えないでよ」という問題で頭をかかえたり、PHPを捨てて他の言語に移った人も少なくないでしょう。今回の問題もその一環だと想像しています。
この問題を修正することはそう難しくありません。例えば以下のように修正すればよいです。
for ( $j = 0 ; $j < count($loopbuf) ; $j++ )
あと、もう一カ所直しました。基本的には同じ感じで修正しています。(ただし、これはちょっと言語依存的なやり方です。評価の短絡をしているものと信じて&&でつなげています。)
修正前
for ( $i = 0 ;is_array( $this->loopitem[$loopmode][$i] ) ; $i++ )
for ( $i = 0 ;$i < count($this->loopitem[$loopmode]) &&is_array( $this->loopitem[$loopmode][$i] ) ; $i++ )