¿Es posible agregar código dinámicamente a / extender una clase?

Quiero escribir una especie de sistema “plugin / module” para mi código, y sería mucho más fácil si pudiera “agregar” cosas a una clase después de haberlas definido.

Por ejemplo, algo como esto:

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

Ahí está la clase. Ahora quiero agregarle otra función / variable / const, después de haberla definido.

Me doy cuenta de que esto probablemente no sea posible, pero necesito una confirmación.

Solutions Collecting From Web of "¿Es posible agregar código dinámicamente a / extender una clase?"

No, no puede agregar métodos a una clase ya definida en tiempo de ejecución.

Pero puede crear una funcionalidad similar utilizando __call/__callStatic magic methods.

 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"; 

Esta solución es bastante limitada, pero tal vez funcione para usted

Para agregar / cambiar el comportamiento de las clases en el tiempo de ejecución, debe usar Decorators y / o Strategies. Este es el enfoque preferido de OO sobre recurrir a cualquier enfoque mágico o parche de mono.

Un decorador envuelve una instancia de una clase y proporciona la misma API que esa instancia. Todas las llamadas se delegan a la instancia empaquetada y los resultados se modifican cuando sea necesario.

 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; } // … } 

Para Strategy, vea mi ejemplo más completo en ¿Puedo incluir código en una clase de PHP?

Más detalles y código de ejemplo se pueden encontrar en

Tengo algunos métodos para que pruebes. 🙂 Diviértete codificando.

Método para una sola clase:

 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 ); } } 

Método para cuando quieres tratar con más de una clase:

 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__(); } } 

Ahora intentemos usarlos:

 $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. 

Nota:

Actualmente estoy usando el primer método (solo tengo una clase, las modificaciones son excepciones) en mi propio CMS que he hecho desde cero (http://sitegen.com.au), y funciona muy bien, mi razón para necesitar esto es porque tengo mi main_class que se está generando después de haber requerido todas las modificaciones en ./mods- habilitado / crear funciones y cambiar el funcionamiento de otras funciones, también volveré aquí en otro momento con una solución para dos mods para ambos cambiar una función sin ganar una, ya que se ejecutó primero. He dividido mis complementos en dos, los mods que se ejecutan en cada sitio y los complementos que tienen configuraciones para un sitio y es posible que ni siquiera estén habilitados.
Diviértete progtwigndo.

Puedes extender la clase

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

Al ampliar foo de la clase woo, la funcionalidad en foo se puede usar, mientras que también puedes crear nuevos métodos en woo. Esa es la forma más fácil de agregar nuevas funcionalidades a una clase.

Puede utilizar la funcionalidad mágica de PHP para proporcionar acciones en métodos que no están definidos en tiempo de comstackción.

En realidad es posible. Por ejemplo:

 < ?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; ?> 

Si no es suficiente magia para ti, puedes usar objetos dynamics. La idea común está aquí: https://github.com/ptrofimov/jslikeobject