Можно ли динамически добавлять код для расширения класса?

Я хочу написать своего рода систему «plugin / module» для моего кода, и это облегчило бы, если бы я мог «добавить» материал в класс после того, как он был определен.

Например, что-то вроде этого:

class foo { public function a() { return 'b'; } } 

Там класс. Теперь я хочу добавить к нему другую функцию / переменную / const после ее определения.

Я понимаю, что это, вероятно, невозможно, но мне нужно подтверждение.

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

Но вы можете создать аналогичную функциональность, используя __call/__callStatic magic.

 Class Extendable { private $handlers = array(); public function registerHandler($handler) { $this->handlers[] = $handler; } public function __call($method, $arguments) { foreach ($this->handlers as $handler) { if (method_exists($handler, $method)) { return call_user_func_array( array($handler, $method), $arguments ); } } } } Class myclass extends Extendable { public function foo() { echo 'foo'; } } CLass myclass2 { public function bar() { echo 'bar'; } } $myclass = new myclass(); $myclass->registerHandler(new myclass2()); $myclass->foo(); // prints 'foo' echo "\n"; $myclass->bar(); // prints 'bar' echo "\n"; 

Это решение довольно ограничено, но, возможно, оно будет работать для вас

Чтобы добавить / изменить поведение классов во время выполнения, вы должны использовать Decorators и / или Strategies. Это предпочтительный подход OO к использованию любых магических подходов или патчей обезьян.

Декоратор обертывает экземпляр класса и предоставляет тот же API, что и этот экземпляр. Любые вызовы делегируются обернутому экземпляру, и результаты при необходимости изменяются.

 class Decorator { // … public function __construct($decoratedInstance) { $this->_decoratedInstace = $decoratedInstance; } public function someMethod() { // call original method $result = $this->_decoratedInstance->someMethod(); // decorate and return return $result * 10; } // … } 

Для стратегии см. Мой более полный пример: могу ли я включить код в класс PHP?

Более подробную информацию и примерный код можно найти по адресу

У меня есть несколько способов попробовать. 🙂 Получайте удовольствие от кодирования.

Метод только для одного класса:

 class main_class { private $_MODS = array(),...; public ...; public function __construct(...) { ... global $MODS_ENABLED; $this -> $_MODS = $MODS_ENABLED; } ... public function __get( $var ) { foreach ( $this->_MODS as $mod ) if ( property_exists( $mod, $var ) ) return $mod -> $var; } public function __call( $method, $args ) { foreach ( $this->_MODS as $mod ) if ( method_exists( $mod, $method ) ) return call_user_method_array( $method, $mod, $args ); } } 

Метод, когда вы хотите иметь дело с несколькими классами:

 class modMe { private $_MODS = array(); public function __construct__() { global $MODS_ENABLED; $this -> $_MODS = $MODS_ENABLED; } public function __get( $var ) { foreach ( $this->_MODS as $mod ) if ( property_exists( $mod, $var ) ) return $mod -> $var; } public function __call( $method, $args ) { foreach ( $this->_MODS as $mod ) if ( method_exists( $mod, $method ) ) return call_user_method_array( $method, $mod, $args ); } } class mainClass extends modMe { function __construct(...){ $this -> __construct__(); } } 

Теперь попробуйте использовать их:

 $MODS_ENABLED = array(); $MODS_ENABLED[] = new mod_mail(); $myObj = new main_class(...); $myObj -> mail("me@me.me","you@you.you","subject","message/body","Extra:Headers;More:Headers"); # Hey look, my mail class was just added into my main_class for later use. 

Заметка:

В настоящее время я использую первый метод (у меня есть только один класс, мода – исключения) в моей собственной CMS, которую я сделал с нуля (http://sitegen.com.au), и он отлично работает, моя причина в необходимости это потому, что у меня есть мой основной_класс, который генерируется после того, как мне потребовались все моды в ./mods-enabled/*, создавая функции и изменяя работу других функций, я также вернусь сюда еще раз с решением для двух модов для обоих смените функцию без выигрыша, когда она работает в первую очередь. Я разделил свои плагины на два, моды, которые запускаются на каждом сайте, и плагины, у которых есть настройки для сайта, и могут даже не включаться.
Получайте удовольствие от программирования.

Вы можете расширить класс

 class foo { public function a() { return 'b'; } } class woo extends foo { public function newStuff() { $var = $this->a(); echo $var; } } 

Расширяя foo из класса woo, функциональность в foo применима, а вы также можете создавать новые методы в woo. Это самый простой способ добавить новую функциональность в класс.

Вы можете использовать магические функции PHP для обеспечения действий над методами, которые не определены во время компиляции.

Это действительно возможно. Например:

 <?php class Test { function set($set, $val) { $this->$set = $val; } function get($get) { return $this->$get; } } $t = new Test(); $t->set('hello', 'world'); echo $t->get('hello'); exit; ?> 

Если для вас недостаточно магии, вы можете использовать динамические объекты. Общая идея здесь: https://github.com/ptrofimov/jslikeobject