この連載は基本的にPHP4.
特に記述がない場合、
リファレンス仕様の変更
PHP4.
Zendエンジンの修正によりメモリ破壊は発生しなくなりましたが、
http://
<?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.
array(3) { [0]=> &string(1) "a" [1]=> &string(1) "b" [2]=> &string(1) "c" }
PHP4.
array(3) { [0]=> &string(1) "c" [1]=> &string(1) "c" [2]=> &string(1) "c" }
と実行結果が異なります。構文的には新しい動作が正しい動作になります。ほかにもリファレンス関連の動作使用の修正が行われています。詳しくはhttp://
無効な配列アクセス
[]を利用して配列変数を読むことはできません。現在のPHP4、
<?php
$a[] = 1;
$b = $a[];
?>
[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
[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では動作し、
<?php
if (defined('MY_FUNCITON')) {
return;
}
define('MY_FUNCTION', 'defined');
function my_function() {}
?>
<?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_
<?php
include_once 'my_function.php';
my_function();
// my_function.phpは読み込み済みで読み込まれない
// エラー無しに実行される
include_once 'my_function.php';
?>
PHPバイナリの名前
前回も紹介しましたが古いPHPではCGI用のバイナリが「php」から
長い名前のシステム定義配列
最近のPHPアプリケーションでは見かけなくなりましたが、
register_long_arrays=on
をphp.
register_globals=off
register_
アプリケーションがregister_
参照カウンタの32ビット化
PHP4からPHP5へ移行する場合の注意点ではありませんが、
<?php
$max = 1 << 16;
$v = 123;
for ($i = 1; $i < $max; $i++) {
$arr[] = &$v;
}
echo $v;
?>
[yohgaki@dev php4-php5-migration]$ ./php4 reference_counter.php 123 *** glibc detected *** /usr/local/php-4.4.7/bin/php: free(): invalid next size (fast): 0x09029b78 *** ======= Backtrace: ========= /lib/libc.so.6[0x79c211] /lib/libc.so.6(__libc_free+0x83)[0x79d863] /usr/local/php-4.4.7/bin/php(shutdown_memory_manager+0x82)[0x8162142] /usr/local/php-4.4.7/bin/php(php_request_shutdown+0x2f7)[0x8143b67] /usr/local/php-4.4.7/bin/php(main+0x3b9)[0x818bbf9] /lib/libc.so.6(__libc_start_main+0xdc)[0x75074c] /usr/local/php-4.4.7/bin/php(gdImageCreateFromPngCtx+0x145)[0x806d5b1]
[yohgaki@dev php4-php5-migration]$ ./php5 reference_counter.php 123
PHP4ではメモリエラーでクラッシュしていることが分かります。PHPがクラッシュするとWeb環境ではページに何も表示されずログにもなにも記録されていない場合がほとんどです。Web環境でクラッシュを検出するにはgdbなどのデバッガを利用できますが、
PHP5に移行することにより参照カウンタのオーバーフローによる原因不明のクラッシュで悩まされることはなくなると思います。
オブジェクト関連の変更
PHP5になりオブジェクト指向プログラミングをサポートする機能が強化されました。PHP4では関数の戻り値がオブジェクト変数であってもオブジェクト変数としてアクセスできない、
オブジェクト変数の代入
PHP4のオブジェクト変数は、
<?php
class foo {var $v = 0;} // 空のクラス定義
$obj1 = new foo; // オブジェクトの生成
$obj2 = $obj1; // $obj2はPHP4ではコピー、PHP5では同じオブジェクト
$obj2->v = 1;
var_dump($obj1, $obj2);
?>
object(foo)(1) {
["v"]=>
int(0) ←ここが異なる
}
object(foo)(1) {
["v"]=>
int(1)
}
object(foo)#1 (1) {
["v"]=>
int(1) ←同じオブジェクトなので$obj2を変更すると同じ値になる
}
object(foo)#1 (1) {
["v"]=>
int(1)
}
非常に大きな問題に見えますが、
$obj2 = &$obj1;
このコードを実行すると、
オブジェクト自身を返すコードの典型的な例は、
$obj = & new foo;
PHP4の場合、
オブジェクトのコピー作成
"="代入演算子によりオブジェクトのコピーが作成されることを期待しているコードは変更が必要です。PHP5は"="代入演算子でコピーが作成できないので、
<?php
class foo {var $v = 0;} // 空のクラス定義
$obj1 = new foo; // オブジェクトの生成
$obj2 = clone $obj1; // コピーが作成され代入される
$obj2->v = 1;
var_dump($obj1, $obj2);
?>
object(foo)#1 (1) {
["v"]=>
int(0) ←コピーを変更しているので値は変わらない
}
object(foo)#2 (1) {
["v"]=>
int(1)
}
PHP5オブジェクトはclone時にどのようにオブジェクトをコピーするか定義するコピーコンストラクタが定義できます。PHP4からPHP5への移行には関係ないので解説は省略します。詳しくはマニュアルや書籍を参照してください。
オブジェクトのコピーが必要になるケースは多くありませんが、
オブジェクト変数の代入がコピーであるかハンドルであるかは、
$this変数の取り扱い
PHP5からオブジェクト自身を表す$this変数が上書きできなくなりました。$thisを上書きすると$thisオブジェクトが別のオブジェクトに変わってしまいます。PHP4の$thisオブジェクト変数が書き換えれる仕様はあまり有用な使い方はできないのでほとんど使われていないと思います。筆者の知っている例では古いPukiwikiは$thisを書き換えていました。
<?php
class foo {
function __construct() {
$this = 123;
$return &$this;
}
}
$obj = new foo;
var_dump($obj);
?>
Fatal error: Cannot re-assign $this in - on line 4
object(foo)(0) { }
PHP4ではエラーなく終了しますが、
まとめ
今回はPHP4.