2013-05-19 8 views
7

Ich habe eine Idee für das Ereignissystem, das ich für mein benutzerdefiniertes Framework entwickle.Können wir noch mehr Zeilen in eine Funktion einfügen, indem wir sie um PHP erweitern?

Stellen Sie sich eine Pseudofunktion wie diese vor.

class Test 
{ 
    public function hi() 
    { 
     Event::add(__FUNCTION__ . 'is about to run.'); 
     return "hi"; 
    } 
} 

Stellen Sie sich vor, Sie müssen dasselbe für einige weitere Funktionen tun. (Vielleicht möchten Sie protokollieren, welche Funktionen zur Laufzeit ausgeführt wurden und diese in einer separaten Datei protokollieren möchten.)

Anstatt dies zu tun und Ereignisse manuell in Funktionen einzufügen, können wir so etwas tun?

class Test 
{ 
    public function hi() 
    { 
     return "hi"; 
    } 
} 

// events.php (It's a pseudo code so may not work.) 
// Imagine extend's purpose is to inject codes into target function 

Event::bind('on', $className, $methodName, function() use ($className, $methodName) 
{ 
    return $className->$methodName->extend('before', Event::add(__FUNCTION__ . 'is about to run.')); 
}); 

Die Idee ist hi() Funktion, die innerhalb Test class ist zu injizieren und Injizieren, was wir von außen in extend Funktion übergeben. 'before' bedeutet, dass die Injektion in der ersten Zeile der Zielfunktion erfolgen muss.

Schließlich werden die Ereignisse und Ereignisbindungen vollständig abstrahiert von den Funktionen entfernt. Ich möchte in der Lage sein, benutzerdefinierte Dinge zu binden, ohne die Funktionen zu ändern.

Ich habe das Gefühl, dass wir dies tun können, indem wir mit eval() herumhacken oder mit call_user_func() spielen. Ich bin mir jedoch nicht sicher. Die Verwendung von eval() klingt schon ziemlich schlecht.

Meine Frage ist;

  1. Ist es eine mögliche Sache mit PHP zu tun?
  2. Hat es einen Namen in OOP/OOP Principles, so kann ich weiter lesen?
  3. Macht es Sinn oder ist es eine schlechte Idee?
+0

Ich dachte, der ganze Sinn der Verwendung von Klassen war, sie wiederzuverwenden? –

+0

Nicht sicher. Ein Proxy vielleicht? –

+2

[Dependency Injection] (http://en.wikipedia.org/wiki/Dependency_injection)? Fowler ist immer eine gute Ressource, wenn es um Designmuster geht. http://www.martinfowler.com/articles/injection.html. ** Vermeiden Sie 'eval' **. – ficuscr

Antwort

2

Ja, Sie können. Sie können AOP mit GO! AOP framework verwenden, die auf Anmerkungen funktioniert.

Zum Beispiel möchten Sie jede öffentliche Methode aufrufen aufrufen. Anstatt jede Funktion hinzuzufügen, wie diese.

namespace Acme; 

class Controller 
{ 
    public function updateData($arg1, $arg2) 
    { 
     $this->logger->info("Executing method " . __METHOD__, func_get_args()); 
     // ... 
    }  
} 

Sie können ein Aspekt für alle öffentlichen Methoden aller Klassen von Acme Namespace wie folgt verwenden:

use Go\Aop\Aspect; 
use Go\Aop\Intercept\MethodInvocation; 
use Go\Lang\Annotation\Before; 

    class LoggingAspect implements Aspect 
    { 
     /** @var null|LoggerInterface */ 
     protected $logger = null; 

     /** ... */ 
     public function __construct($logger) 
     { 
      $this->logger = $logger; 
     } 

     /** 
     * Method that should be called before real method 
     * 
     * @param MethodInvocation $invocation Invocation 
     * @Before("execution(public Acme\*->*())") 
     */ 
     public function beforeMethodExecution(MethodInvocation $invocation) 
     { 
      $obj = $invocation->getThis(); 
      $class = is_object($obj) ? get_class($obj) : $obj; 
      $type = $invocation->getMethod()->isStatic() ? '::' : '->'; 
      $name = $invocation->getMethod()->getName(); 
      $method = $class . $type . $name; 

      $this->logger->info("Executing method " . $method, $invocation->getArguments()); 
     } 
    }  

Es sieht komplizierter aus, aber es ist flexibler.

Verwandte Themen