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

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

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

オブジェクト関連の変更

PHP5になりオブジェクト指向プログラミングをサポートする機能が強化されました。PHP4では関数の戻り値がオブジェクト変数であってもオブジェクト変数としてアクセスできない,例外オブジェクトをサポートしないなど,現在のオブジェクト指向プログラミング言語としては機能的に見劣りしていました。PHP5ではこれらの課題が解決されていますが互換性の問題も発生しています。次の項から次回にかけてはオブジェクト関連の変更を解説します。

オブジェクト変数の代入

PHP4のオブジェクト変数は,ほかの変数と同様に"="(代入演算)でコピーが作成されていました。PHP5からオブジェクト変数はハンドルで取り扱われ,"="代入演算子でオブジェクト変数を代入するとオブジェクトのコピーは作成されず,オブジェクトへのハンドルがコピーされるようになりました。ほかのオブジェクト指向プログラミング言語に近い操作が可能になっています。

例:オブジェクトの代入動作の違い

<?php
class foo {var $v = 0;}    // 空のクラス定義
$obj1 = new foo;   // オブジェクトの生成
$obj2 = $obj1;     // $obj2はPHP4ではコピー,PHP5では同じオブジェクト
$obj2->v = 1;
var_dump($obj1, $obj2);
?>

PHP4の出力

object(foo)(1) {
  ["v"]=>
  int(0)   ←ここが異なる
}
object(foo)(1) {
  ["v"]=>
  int(1)
}

PHP5の出力:vプロパティは両方1

object(foo)#1 (1) {
  ["v"]=>
  int(1)   ←同じオブジェクトなので$obj2を変更すると同じ値になる
}
object(foo)#1 (1) {
  ["v"]=>
  int(1)
}

非常に大きな問題に見えますが,この違いが問題になるケースはあまり多くありません。PHP4でオブジェクトのコピーでなくオブジェクトの参照を作成した場合,"&"参照演算子でオブジェクト変数の参照を作成します。

$obj2 = &$obj1;

このコードを実行すると,PHP4では$obj2変数は$obj1変数の参照になり,$obj1と$obj2は同じオブジェクトへアクセス可能なオブジェクト変数になります。PHP5ではPHP4と同じく$obj2は$obj1の参照になります。違いは通常変数と同じ参照なのか,オブジェクトハンドルの参照なのかだけで結果的に同じ動作になります。

オブジェクト自身を返すコードの典型的な例は,コンストラクタで初期化したオブジェクト自身を返す場合です。

$obj = & new foo;

PHP4の場合,オブジェクト自身を返すため"& new foo"の&演算子は必須でした。PHP5では&演算子の有無に関係なくオブジェクト自身を返すことができます。参照演算子&が利用されてもPHP5で実行した場合に違いが発生することはありません。

オブジェクトのコピー作成

"="代入演算子によりオブジェクトのコピーが作成されることを期待しているコードは変更が必要です。PHP5は"="代入演算子でコピーが作成できないので,Java言語のようにclone文が用意されています。

例:clone文の利用

<?php
class foo {var $v = 0;}  // 空のクラス定義
$obj1 = new foo;         // オブジェクトの生成
$obj2 = clone $obj1;     // コピーが作成され代入される
$obj2->v = 1;
var_dump($obj1, $obj2);
?>

PHP5での実行例

object(foo)#1 (1) {
  ["v"]=>
  int(0)     ←コピーを変更しているので値は変わらない
}
object(foo)#2 (1) {
  ["v"]=>
  int(1)
}

PHP5オブジェクトはclone時にどのようにオブジェクトをコピーするか定義するコピーコンストラクタが定義できます。PHP4からPHP5への移行には関係ないので解説は省略します。詳しくはマニュアルや書籍を参照してください。

オブジェクトのコピーが必要になるケースは多くありませんが,本当にコピーが必要だった場合にはプログラムが誤作動するので確認が必要です。

オブジェクト変数の代入がコピーであるかハンドルであるかは,オブジェクト変数の比較に大きな影響を与えます。オブジェクト変数の比較については別の項目で解説します。

著者プロフィール

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

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

URLhttp://blog.ohgaki.net/

著書