[PHP-users 9232] Re: (メザコ?)クラス関数とオブジェクト関数で同一名を使うには?
Mashiki
php-users@php.gr.jp
Thu, 08 Aug 2002 09:54:17 +0900
Mashikiです。
しょうなりさん、情報ありがとうございます。
>目的のクラスとまったく関係ないオブジェクト内から
>目的のクラス内で isset($this) したということですね?
>class A {
> function A () {
> print get_class($this)." : "; // class名の出力
> print (isset($this)) ? "OBJECT" : "CLASS";
> print "<BR>";
> }
>}
>
>class B {
> function B () {
> A::A();
> }
>}
>
>A::A();
>$OB = new B;
最初は、ふ〜んこんなこともできるんだ。ひまがあったら
ためしてみよっっと思って読み流していたのですが、僕が遭遇
した状況はこれが原因のようです。
>先日僕も気付いて、多重継承みたいなことができて便利って
>思っていました。
>(class A のメソッドで class B のプロパティを操作できます)
便利って言うよりすごく怖いですね。
ひどく直感に逆らう仕様と感じます。
僕が書いたのはDBのコネクションとエラー処理を管理するクラスで、
query()というメソッドとPEARのDBを格納するオブジェクト変数$dbを
用意していました。
query()はオブジェクト関数として呼ばれていればそのオブジェクトが
持っているDBで、クラス関数として呼ばれていればデフォルトのDBで、
SQLを実行するメソッドでした。
簡単に書くとこんな感じです。
class ConnectDB {
var $db;
function ConnectDB($DSN) {
$db = DB::connect($DSN);
}
function &query($sql) {
global $default_ConnectDB;
if (isset($this)) {
$dbConn =& $this;
} else {
$dbConn =& $default_DB_connect;
}
return $dbConn->db->query($sql);
}
}
これをクラス関数として呼び出す場合、クラス内でない通常の関数や
関数の外側の通常のコードから呼び出す場合には普通に機能しますが、
他のオブジェクトの中の関数から呼び出された場合、そのオブジェク
トには、変数dbは無いのでエラーとなってしまいます。
デバッグの途中でこの関数の最初にprint_r($this)を入れてみたところ
まったく関係ないクラスの情報が出てきてしまい最初のメールをしました。
再現させようといろいろ試したのですが、オブジェクト関数から呼ぶ
というのは気が付きませんでした。
まとめると
isset($this)はオブジェクト関数として呼ばれた場合と
任意のクラスのオブジェクトからクラス関数として呼ばれた
場合に真になり、全てのオブジェクトの外側から呼ばれた
場合に偽になるということですか。
クラスの再利用を考えるとisset($this)による判断は避けたほうが
安全みたいですね。
PEARクラスの「静的メソッドとして PEAR::setErrorHandling()をコール」
する場合も必ずコードの一番外側の階層から呼ばないとうまく機能しない
ようですね。
$thisの仕様は納得がいかないのですが、しょうなりさんのおかげで
うまくいかない理由は理解できました。
本当にありがとうございました。