日記
PHPのオブジェクトとリファレンス (13:48)Edit

PHPオブジェクトリファレンス周りの仕様は大嫌いなんだけど、それを何とか使いこなすために試行錯誤中。問題なのは、

  • インスタンスの変数への代入=インスタンスのコピーの作成であること
  • インスタンスを返す関数に直接続けてインスタンスの機能を呼び出すコードが書けないこと

たとえば、

class ClassA{
var $value;
function Set($newvalue){
$this->value=$newvalue;
}
function Get(){
return $this->value;
}
}

なんて値を保持する簡単なクラスがある。で、そのクラスのインスタンスをグローバルに一つ生成しておいて、あちこちで手軽にそれを使い回したいと思う。

global $a;
$a=new ClassA();

なんてすることで、グローバル変数$aにClassAのインスタンスが生成される。あとはカレントスコープがグローバルな場所ならば、

$a->Set("newvalue");

なんて感じで$aにアクセスできる。でも、スコープがローカルな場所ならば、

function func(){
global $a;
$a->Set("newvalue");
}

なんて感じで、いちいち$aがglobalであることを宣言しないといけない。それがいやなんで、どこからでも同じ表現でアクセスできるようなインターフェースを用意してみようかと思った。たとえば、

function &IA(){
global $a;
return $a;
}

なんて関数を用意すれば、カレントのスコープがグローバルだろうがローカルだろうが、IA()でグローバルな$aへの参照が返される。しかし、PHPでは関数が返したインスタンス変数への参照を使って、直接そのインスタンス変数の機能を呼び出すことは許されていないらしい。たとえば、

IA()->Set("newvalue");

なんて書くとタイムアウトまで固まってしまう。

$b=&IA();
$b->Set("newvalue");

というように、いったんローカル変数にインスタンスの参照を受け取ってからSetすると、きちんとグローバルな$aに値がセットされるのだが、これならばいちいちglobal $a;を記述するのと大差ないだろう。

ちなみに余談だが、

$b=IA();
$b->Set("newvalue");

は間違い。これはグローバルな$aのコピーである$bに対して値をセットしているだけなので、グローバルな$aには値はセットされない。

このあたりはとてもわかりにくい仕様だ。出来れば代入処理は、stringやintegerみたいな型に対して行った場合はコピーになり、その他オブジェクト型に対して行った場合は参照の代入になるといいんだけど。

ちなみにグローバルなインスタンス変数に対して、どのスコープからでも一意な表現でアクセスする手段としては、

$GLOBALS["a"];

を使うという方法もある。でも$GLOBALSを使った表現は見た目が美しくないので使いたくない。あと、

define("a",new ClassA());

なんてやったらどこでも、

a->Set("newvalue");

なんて出来るようになるんじゃないかと思ったら、あいにく定数にはオブジェクト型は入れられないそうな。

というわけで、現在手詰まり状態(動くことは動くけどね)。グローバルなインスタンス変数に対して、どのスコープからも手軽にアクセスできるような手段はないものかのー。

Published At2002-12-27 00:00Updated At2002-12-27 00:00