WordPressをCMSとして使用しており、別のクラスから継承せずにそのクラスの1つを拡張したい、つまり、そのクラスにメソッドを「追加」したいだけです。
class A {
function do_a() {
echo 'a';
}
}
その後:
function insert_this_function_into_class_A() {
echo 'b';
}
(後者をAクラスに挿入する何らかの方法)
そして:
A::insert_this_function_into_class_A(); # b
これは粘り強いPHPでも可能ですか?
クラスのパブリックAPIにアクセスするだけでよい場合は、 デコレータ を使用できます。
class SomeClassDecorator
{
protected $_instance;
public function myMethod() {
return strtoupper( $this->_instance->someMethod() );
}
public function __construct(SomeClass $instance) {
$this->_instance = $instance;
}
public function __call($method, $args) {
return call_user_func_array(array($this->_instance, $method), $args);
}
public function __get($key) {
return $this->_instance->$key;
}
public function __set($key, $val) {
return $this->_instance->$key = $val;
}
// can implement additional (magic) methods here ...
}
次に、SomeClassのインスタンスをラップします。
$decorator = new SomeClassDecorator(new SomeClass);
$decorator->foo = 'bar'; // sets $foo in SomeClass instance
echo $decorator->foo; // returns 'bar'
echo $decorator->someMethod(); // forwards call to SomeClass instance
echo $decorator->myMethod(); // calls my custom methods in Decorator
protected
APIにアクセスする必要がある場合は、継承を使用する必要があります。 private
APIにアクセスする必要がある場合は、クラスファイルを変更する必要があります。継承アプローチは問題ありませんが、クラスファイルを変更すると、更新時に問題が発生する可能性があります(作成されたパッチはすべて失われます)。ただし、どちらもrunkitを使用するよりも実行可能です。
スコープに対応する2014年の更新された方法。
public function __call($method, $arguments) {
return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
}
例えば:
class stdObject {
public function __call($method, $arguments) {
return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
}
}
$obj = new stdObject();
$obj->test = function() {
echo "<pre>" . print_r($this, true) . "</pre>";
};
$obj->test();
これには runkit拡張 を使用できますが、代わりに通常の継承を検討する必要があります。
見る - runkit_method_add
。
問題のクラスが__callマジックを実装している場合、それは可能であり、非常に簡単です。これがどのように機能するかを知りたい場合は、 実行時に新しいメソッドでオブジェクトを拡張する を読むことをお勧めします。