残り一年! PHP4からPHP5への移行

第2回 PHP4.4以前からの移行とPHP5におけるオブジェクトの仕様変更

この記事を読むのに必要な時間:およそ 4.5 分

この連載は基本的にPHP4.4.xユーザがPHP5.2.xに移行する場合の注意点を解説しています。しかし,実際にはPHP4.4.xより前のPHPを利用されているユーザも多いと思います。ここではこれらのバージョンを利用しているユーザ向けに,重要な変更箇所を解説します。後半はオブジェクト関連の変更を解説します。

特に記述がない場合,PHP4はPHP4.4.x,PHP5はPHP5.2.xを意味します。

リファレンス仕様の変更

PHP4.4.0はPHP5.1.0と同時にリリースされました。Zendエンジンの仕様やその他の機能拡張を含めたリリースでした。Zendエンジンの変更には不適切なリファレンスの使用によりメモリ破壊が発生するバグを修正するためのリリースも含まれていました。

Zendエンジンの修正によりメモリ破壊は発生しなくなりましたが,一部動作仕様が変更されたり,エラーとなるようになりました。PHP4.4に移行していないユーザの場合,動作していたプログラムが動作しなくなったり,動作が変わる場合があります。しかし,動作が変わったり動作しなくなるケースは元々リファレンスの使用方法が間違っていたり不適切な場合です。大きな影響はないはずです。

PHPマニュアルに記載されている例

http://www.php.net/manual/en/migration51.references.php#migration51.references-fails

<?php
function func(&$arraykey) {
    return $arraykey; // function returns by value!
}

$array = array('a', 'b', 'c');
foreach (array_keys($array) as $key) {
    $y = &func($array[$key]);
    $z[] =& $y;
}

var_dump($z);
?>

このコードをPHP4.4.0未満,PHP5.1.0未満で実行すると

array(3) {
  [0]=>
  &string(1) "a"
  [1]=>
  &string(1) "b"
  [2]=>
  &string(1) "c"
}

PHP4.4.0以上, PHP5.1.0以上で実行すると

array(3) {
  [0]=>
  &string(1) "c"
  [1]=>
  &string(1) "c"
  [2]=>
  &string(1) "c"
}

と実行結果が異なります。構文的には新しい動作が正しい動作になります。ほかにもリファレンス関連の動作使用の修正が行われています。詳しくはhttp://www.php.net/manual/en/migration51.references.phpを参照してください。

無効な配列アクセス

[]を利用して配列変数を読むことはできません。現在のPHP4,PHP5では[]を利用した配列変数の読み取りはFatalエラーを発生させます。

例:[]は読み取りには利用できない

<?php
$a[] = 1;
$b = $a[];
?>

実行例:PHP4

[yohgaki@dev php4-php5-migration]$ ./php4 invalid-array-reading.php

Fatal error: Cannot use [] for reading in /home/yohgaki/php4-php5-migration/invalid-array-reading.php on line 3

実行例:PHP5

[yohgaki@dev php4-php5-migration]$ ./php5 invalid-array-reading.php

Fatal error: Cannot use [] for reading in /home/yohgaki/php4-php5-migration/invalid-array-reading.php on line 3

関数定義仕様の変更

古いPHP4では関数定義は実行時に動的に生成されていました。PHP5から関数定義はコンパイル時に定義されます。この仕様変更により次の例のコードは古いPHP4では動作し,現在のPHP4, PHP5では動作しません。

関数を定義するファイル ─ my_functions.php

<?php
if (defined('MY_FUNCITON')) {
   return;
}
define('MY_FUNCTION', 'defined');

function my_function() {}
?>

関数定義をファイルmy_function.phpを読み込むファイル ─ my_function_caller.php

<?php
include 'my_function.php';

my_function();

include 'my_function.php';
?>

実行例

[yohgaki@dev php4-php5-migration]$ /usr/local/php-4.4.7/bin/php my_function_caller.php

Fatal error: Cannot redeclare my_function() (previously declared in /home/yohgaki/php4-php5-migration/my_function.php:7) in /home/yohgaki/php4-php5-migration/my_function.php on line 7

my_function.phpのようなコードはinclude_once/require_onceが実装される前に重複した関数定義エラーなどを防ぐために利用されていました。かなり古いPHP用に書かれたPHPコードでなければ見られないスタイルです。現在では関数/クラスを定義するファイルを読み込む場合はrequire_once/include_onceを利用します。

関数定義をファイルmy_function.phpを読み込む

<?php
include_once 'my_function.php';

my_function();

// my_function.phpは読み込み済みで読み込まれない
// エラー無しに実行される
include_once 'my_function.php';
?>

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書

コメント

コメントの記入