11
votes

PHP: enveloppez toutes les fonctions d'une classe dans une sous-classe

Travailler avec une classe de bibliothèque PHP, et j'aimerais envelopper toutes ses fonctions publiques dans une sous-classe ... quelque chose du long des lignes de: xxx

en bouillant, je «D Préférez-vous ne pas avoir à remplacer chaque méthode Superclass avec le même code d'emballage, s'il y a un moyen [un peu élégant / propre] de tout faire au même endroit.

est-ce possible? Je soupçonne que je suis en métaprogramming Terre ici et je ne sais même pas si PHP offre une telle bête, mais je me suis dit que je vous demanderais ...


4 commentaires

Pour clarifier - il n'y a que certaines méthodes de basoclass que vous souhaitez remplacer dans sous-classe , pas tous?


@ S992, pas exactement - je cherchais un moyen d'appliquer le même code d'emballage à chaque méthode de la classe de base. On dirait que la méthode de la magie __Call de PHP fera le travail avec une enveloppe proxy, merci @meagar!


Gotcha, la question n'était pas exactement claire. Si la réponse de MEAGAR vous a aidé, vous devriez l'accepter. :)


Ce que vous voulez s'appelle AOP. Il existe des réalisations de AOP dans PHP: Extension PHP-AOP, Allez! Bibliothèque AOP, TYPO3 Flow AOP.


4 Réponses :


0
votes

Vous recherchez peut-être le motif de décorateur:

class A
{
   function do1(){

   }
}
class DecoratorForA extends A
{
   private A original;
   public DecoratorForA( A original )
   {
      this.original = original;
   }
   function do1(){  //<-- override keyword in php?
      stuffBefore(); 
      original->do1();
      stuffAfter();      
   }
}


3 commentaires

Oh, maintenant je l'ai lu correctement, devinez que vous ne cherchez pas cela.


Il essaie de trouver un moyen simple d'appliquer généralement le motif de décorateur sans écrire une magnitude de code de la chaudron. Vous venez de donner ses besoins un nom, pas une solution ...


Correct, je cherchais une application de métaprogrammation du motif de décorateur ... Merci pour votre contribution, cependant!



2
votes

Si les noms de sous-classe de la sous-classe peuvent différer légèrement des noms de méthode d'origine de la base de base, vous pouvez écrire une enveloppe générique avec __ appel () . Si les noms de méthode doivent correspondre, je ne vois pas comment vous pourriez atteindre votre objectif sans écraser manuellement chaque méthode. Peut-être que vous pourriez utiliser le Funcall Pecl pour le faire - mais vous devrez être capable de charger ce pecl en premier lieu.

Si vous pouvez faire les méthodes de base de base protégée , la __ appel () approche de sous-classe fonctionnera.

Si vous ne BESOIN pour étendre la classe, l'approche de Maeger est parfaitement parfaite. Veuillez noter que __Call () et Call_user_func_array () imposent une certaine surcharge.


1 commentaires

C'est une chose importante à souligner - merci. Je n'ai pas (je pense que je n'ai pas besoin d'étendre la classe, alors je prévois que l'approche proxy fonctionnera. (Dépendra de la manière dont le routage de CodeDigniter est effectué sous la hotte)



24
votes

Vous pouvez le faire facilement avec le __Call code> Méthode magique et a La classe "Proxy" générique qui n'hérite pas directement de la classe de base.

Voici une mise en œuvre complète (proche) d'une classe de proxyage qui enveloppe l'objet que vous le transmettez. Il sera invoqué certains "avant" et "après" CODE autour de chaque appel de méthode. P>

class MyProxy {
  function __construct($object) {
    $this->object = $object;
  }

  function __call($method, $args) {
    // Run before code here

    // Invoke original method on our proxied object
    call_user_func_array(array($this->object, $method), $args);

    // Run after code here
  }
}


$base = new BaseClass();
$proxy = new MyProxy($base);

$proxy->doSomething(); // invoke $base->doSomething();


2 commentaires

Une façon de contourner le problème de type consiste à examiner la manière dont la version PHP de Mockito, Phockito, génère des classes simulées. github.com/hafriedlander/phockito/blob/master/phockito.php# L 170


Qu'en est-il si une méthode a un paramètre de référence? "Fonction publique (et sortie $) {}"



0
votes

Si je vous comprends bien, vous souhaitez étendre une classe, mais ne permettez aucune des méthodes du parent à être appelées. Au lieu de cela, vous souhaitez appeler toutes les méthodes dans une méthode de la nouvelle classe.

Alors pourquoi voulez-vous même hériter en premier lieu? Cela ressemble beaucoup à ce que vous devriez simplement créer un adaptateur / décorateur pour votre base de base. xxx


0 commentaires