Как добавить метод к существующему классу в PHP?

Я использую WordPress как CMS, и я хочу расширить один из его классов, не наследуя от другого класса; т.е. я просто хочу «добавить» к этому классу больше методов:

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?

Если вам нужен только доступ к Public API этого класса, вы можете использовать Decorator :

 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, то это возможно и довольно легко. Если вы хотите знать, как это работает, я предлагаю вам прочитать во время выполнения чтение объектов с новыми методами .

Нет, вы не можете динамически изменять класс во время выполнения на PHP.

Вы можете выполнить это путем расширения класса с использованием обычного наследования:

 class Fancy extends NotSoFancy { public function whatMakesItFancy() //can also be private/protected of course { // } } 

Или вы можете редактировать исходные файлы WordPress.

Я предпочел бы путь наследования. В долгосрочной перспективе это намного проще.