Comment ajouter une méthode à une classe existante en PHP?
J'utilise WordPress comme CMS, et je veux étendre une de ses classes sans avoir à hériter d'une autre classe; i.e. je veux simplement "ajouter" plus de méthodes à cette classe:
class A {
function do_a() {
echo 'a';
}
}
puis:
function insert_this_function_into_class_A() {
echo 'b';
}
(d'une certaine façon de l'insertion de ce dernier dans Une classe)
et:
A::insert_this_function_into_class_A(); # b
est-ce même possible en PHP tenace?
5 réponses
si vous n'avez besoin que d'accéder à L'API publique de la classe, vous pouvez utiliser un Décorateur:
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 ...
}
puis envelopper L'instance de 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
Si vous avez besoin d'avoir accès à l' protected
API, vous devez utiliser l'héritage. Si vous avez besoin d'accéder à l' private
API, vous devez modifier les fichiers de classe. Alors que l'approche de l'héritage est correcte, modifier les fichiers de classe peut vous causer des problèmes lors de la mise à jour (vous perdrez tous les correctifs apportés). Mais les deux sont plus réalisables que l'utilisation de runkit.
une nouvelle façon pour 2014 qui s'adapte à scope.
public function __call($method, $arguments) {
return call_user_func_array(Closure::bind($this->$method, $this, get_called_class()), $arguments);
}
par exemple:
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();
Vous pouvez utiliser l'extension runkit pour cela, mais vous devriez vraiment envisager l'héritage régulier à la place.
Voir runkit_method_add
.
si la classe en question implémente _ _ call magic, alors c'est possible, et assez facile. Si vous voulez savoir comment cela fonctionne, je vous conseille de lire extension des objets avec de nouvelles méthodes à l'exécution.
Non vous ne pouvez pas changer dynamiquement une classe pendant l'exécution en PHP.
Vous pouvez accomplir ceci en étendant la classe en utilisant l'héritage régulier:
class Fancy extends NotSoFancy
{
public function whatMakesItFancy() //can also be private/protected of course
{
//
}
}
ou vous pouvez éditer les fichiers source Wordpress.
je préférerais l'héritage. C'est beaucoup plus facile à gérer à long terme.