Home > PHP > PHP4なスクリプトをPHP5へ移行する際に発生する7つの問題

PHP4なスクリプトをPHP5へ移行する際に発生する7つの問題

  • 2007-06-06 (水) 23:11
  • PHP
  • このエントリーをはてなブックマークに追加
この記事の所要時間: 119

2007/11/13: 3.と4.が同じ内容となっていましたので、4.の内容を変更しました。

ここ最近PHP4.1.2で稼働していたシステムをPHP5.1.6へ移行しています。

移行の際に発生した問題とその対応をメモしておきます。

ちなみに全ての内容がPHP4->PHP5で必要なものではないです。PHP4も4.1/4.2/4.3/4.4の間でちょこちょこ変わっているので、一部の内容はPHP4間の移行でも修正が必要になります。またPHP4.4に適応しているスクリプトをPHP5へ移行するなら修正内容は少なくなります。

1.Notice: Only variable references should be returned by reference

「function &method()」と定義しているメソッドでスカラー値を返すと発生します。

PHP:
  1. <?php
  2. class Hoge {
  3.   function &method() {
  4.     return false;
  5.   }
  6. }
  7. Hoge::method();

「function method()」にするか、本当に参照を返す必要がある場合ならスカラー値を一旦変数に代入してからreturnします。

PHP:
  1. <?php
  2. class Hoge {
  3.   // 参照を返さなくて良いなら
  4.   function method() {
  5.     return false;
  6.   }
  7.  
  8.   // 参照を返す必要があるなら
  9.   function &method() {
  10.     $ret = false;
  11.     return $ret;
  12.   }
  13. }

2.get_class()がクラス名を小文字で返さない

get_class()でクラス名を判定している時にはまります。PHP4ではクラス名が小文字(hoge)で返されるのに対してPHP5ではクラス名(Hoge)がそのまま返ります。

PHP:
  1. <?php
  2. class Hoge {}
  3.  
  4. $obj = new Hoge();
  5. if (get_class($obj) == 'hoge') {
  6.   // PHP4ならこちらを通る
  7. } else {
  8.   // PHP5ならこちらを通る
  9. }

PHP5専用で良いなら比較するクラス名を実際のクラス名(Hoge)に変更します。PHP4との互換性が必要ならget_class()の返り値をstrtolower()で小文字にします。

PHP:
  1. <?php
  2. class Hoge {}
  3.  
  4. $obj = new Hoge();
  5. // クラス名を変える
  6. if (get_class($obj) == 'Hoge') {
  7. }
  8.  
  9. // 小文字にする
  10. if (strtolower(get_class($obj)) == 'hoge') {
  11. }

3.Notice: Trying to get property of non-object

PHP4では値がnullな変数のインスタンス変数もnullでした。($obj = nullなら$obj->idもnull)この仕様の是非はともかく、まあこういう仕様でした。PHP5では改善?され、nullな変数のインスタンス変数を参照しようとするとNoticeが発生するようになっています。

PHP:
  1. <?php
  2. $obj = null;
  3. if (is_null($obj->id)) {
  4.   echo "foo\n";
  5. }
  6.  
  7. // PHP4.1.2
  8. // foo
  9.  
  10. // PHP5.1.6
  11. // PHP Notice:  Trying to get property of non-object in /home/shin/tmp/getter.php on line 3
  12. // foo

$obj->idをempty()で判定するか、$objがnullか否かを判定します。

PHP:
  1. <?php
  2. $obj = null;
  3. if (empty($obj->id)) {
  4.   echo "foo\n";
  5. }
  6.  
  7. if (!is_null($obj) && is_null($obj->id)) {
  8.   echo "foo\n";
  9. }

4.PHP Fatal error: Cannot redeclare

PHP4.1.2では同じ名前のメソッドが複数存在してもエラーにはなりませんでした。(単に後で定義したメソッドが呼ばれる)PHP5ではFatalエラーが発生します。

PHP:
  1. <?php
  2. class Hoge {
  3.   function a() {
  4.     echo "foo\n";
  5.   }
  6.  
  7.   function a() {
  8.     echo "bar\n";
  9.   }
  10. }
  11.  
  12. $obj = new Hoge();
  13. $obj->a();
  14.  
  15. // PHP4.1.2
  16. // bar
  17.  
  18. // PHP5.1.6
  19. // PHP Fatal error:  Cannot redeclare Hoge::a() in /home/shin/tmp/same_method.php on line 7
  20. ?>

5.short_open_tagがoff

ソースに含まれるphp.ini-recommendでは[short_open_tag=off]になっています。もし必要な場合はOnにしておきます。

6.Fatal error: Cannot redeclare method()

PHP4.1.2ではクラス内に同名のメソッドがあっても動作していました(後で定義した方が有効)。PHP5.1.6ではFatal errorが発生するようになっています。(確かPHP4.3.0あたりからこうなってたと思います。)

PHP:
  1. <?php
  2. class Hoge {
  3.   function method() {
  4.     echo "method1\n";
  5.   }
  6.   function method() {
  7.     echo "method2\n";
  8.   }
  9. }
  10.  
  11. Hoge::method();

先に定義されているメソッドはどこからも呼ばれていないはずなので削除するか、もし必要ならば別のメソッド名にします。

7.array_push()では参照を格納する

PHP5のオブジェクトは参照渡しが基本となっているので、array_push()でもオブジェクトの参照が連想配列に格納されます。ですのでループ内等で連続でarray_push()する際は注意する必要があります。

下の例ではPHP4.1.2ではidが異なるオブジェクトが格納されていますが、PHP5.1.6ではどちらも同じidになっているのが分かります。

PHP:
  1. <?php
  2. $array = array();
  3. $a = new stdClass;
  4. for ($i = 1; $i <= 2; $i++) {
  5.   $a->id = $i;
  6.   array_push($array, $a);
  7. }
  8.  
  9. var_dump($array);
  10.  
  11. // PHP4.1.2
  12. // array(2) {
  13. //   [0]=>
  14. //   object(stdClass)(1) {
  15. //     ["id"]=>
  16. //     int(1)
  17. //   }
  18. //   [1]=>
  19. //   object(stdClass)(1) {
  20. //     ["id"]=>
  21. //     int(2)
  22. //   }
  23. // }
  24.  
  25. // PHP5.1.6
  26. // array(2) {
  27. //   [0]=>
  28. //   object(stdClass)#1 (1) {
  29. //     ["id"]=>
  30. //     int(2)
  31. //   }
  32. //   [1]=>
  33. //   object(stdClass)#1 (1) {
  34. //     ["id"]=>
  35. //     int(2)
  36. //   }
  37. // }

PHP5ではオブジェクトを毎回newするか__cloneする必要があります。

PHP:
  1. <?php
  2. // new
  3. $array = array();
  4. for ($i = 1; $i <= 2; $i++) {
  5.   $a = new stdClass;
  6.   $a->id = $i;
  7.   array_push($array, $a);
  8. }
  9. var_dump($array);
  10.  
  11. // clone
  12. $array = array();
  13. $a = new stdClass;
  14. for ($i = 1; $i <= 2; $i++) {
  15.   $b = clone $a;
  16.   $b->id = $i;
  17.   array_push($array, $b);
  18. }
  19. var_dump($array);

意外と動きます

バージョン間の互換性が悪いと言われるPHPですが、PHP4.1.2からPHP5.1.6というロングジャンプ;-)でも、意外と動作しました。

専用サーバなどでよく採用されているCentOS(RHEL互換)の最新版(CentOS5)ではPHP5.1.6が採用されました。これにより今後はPHP5への移行が進むのではと期待しています。PHP4なシステムをメンテナンスされている方、一度PHP5環境を試してみてはいかがでしょうか。

ref: PHP: 下位互換性のない変更点 - Manual

トラックバック:2

このエントリーのトラックバックURL
http://www.1x1.jp/blog/2007/06/php_php4_to_php5.html/trackback
Listed below are links to weblogs that reference
PHP4なスクリプトをPHP5へ移行する際に発生する7つの問題 from Shin x blog
pingback from 株式会社 FUCO » Blog Archive » PHP4 -> PHP5 07-06-08 (金) 4:17

[...] PHP4なスクリプトをPHP5へ移行する際に発生する7つの問題 | Shin x blog [...]

trackback from スクラップばんざい 11-01-21 (金) 20:55

[FileMaker][PHP] PHP Site Assistantで生成したサイトでPHPのNoticeが出る対処...

FileMaker Server 11 の PHP Site Assistant で生成したサイトで、部分的にこんなNoticeが表示される場合がある。 Notice: Only variable references should be returned by reference 〜〜 LayoutImpl.php どうもPHPのバージョンによる問題のようで、FileMakerのAPIはPHP4...

Home > PHP > PHP4なスクリプトをPHP5へ移行する際に発生する7つの問題

検索
フィード
メタ情報

Return to page top