Comment intercepter un appel de méthode sur un objet en PHP ?
-
15-09-2020 - |
Question
J'essaie de comprendre comment intercepter n'importe quelle méthode appelée sur un objet en PHP.Je connais la fonction magique __call
, mais il n'est déclenché que pour les méthodes qui n'existent pas sur l'objet appelé.
Par exemple j'ai quelque chose comme ça :
class Foo
{
public function bar()
{
echo 'foobar';
}
public function override($method_name,$method_args)
{
echo 'Calling method ',$method_name,'<br />';
$this->$method_name($method_args); //dirty, but working
}
}
Et quand je fais ça :
$foo = new Foo();
$foo->bar();
Je veux cette sortie :
Calling method bar
foobar
au lieu de celui-ci :
foobar
Existe-t-il un moyen de procéder?Aidez-moi, s'il vous plaît :)
La solution
Prendre votre original Foo
implémentation, vous pouvez envelopper un decorator
autour comme ceci :
class Foo
{
public function bar() {
echo 'foobar';
}
}
class Decorator
{
protected $foo;
public function __construct(Foo $foo) {
$this->foo = $foo;
}
public function __call($method_name, $args) {
echo 'Calling method ',$method_name,'<br />';
return call_user_func_array(array($this->foo, $method_name), $args);
}
}
$foo = new Decorator(new Foo());
$foo->bar();
Autres conseils
Vous pouvez enrouler un objet autour de l'objet, intercepter tous les appels, puis les transférer sur l'objet d'origine et renvoyer le résultat.
Stockez simplement l'objet en tant que variable dans votre classe wrapper et utilisez des méthodes de surcharge dans votre classe wrapper pour appeler/définir/obtenir/vérifier l'objet.
$object = new AnyObject;
$object = new Wrapper($object);
$object->anyMethod();
$object->anyVar = 'test';
echo $object->anyVar;
echo $object['array form'];
Boucler la classe wrapper dans foreach est probablement plus difficile.Je n'ai pas essayé ça.
Si vous définissez la fonction sur private , call interceptera tout appel provenant de l'extérieur qui sera piégé dans __call, mais vous pouvez l'appeler de l'intérieur.
class Foo
{
private function bar()
{
echo 'foobar';
}
public function __call($method_name,$method_args)
{
echo 'Calling method ',$method_name,'<br />';
$this->$method_name(); //dirty, but working
}
}