2013-05-19 23 views
7

Özel çerçevem ​​için geliştirdiğim olay sistemi hakkında bir fikrim var.Bir işlevde PHP ile genişleterek bazı satırları ekleyebilir miyiz?

Böyle bir işlevi düşünün.

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

Bazı işlevler için aynısını yapmanız gerektiğini düşünün. (Belki de, hangi işlevlerin çalışma zamanında çalıştırıldığını ve ayrı bir dosyada oturum açmak istediğini kaydedebilirsiniz.)

Bunu yapmak ve Olayları işlevlere el ile eklemek yerine, bunun gibi bir şey yapabilir miyiz?

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

fikri Test class içindedir ve dışarıda tarafından extend işlevinde geçmesi her ne enjekte hi() fonksiyonunu enjekte etmektir. 'before', enjeksiyonun hedef fonksiyonun ilk satırında olması gerektiği anlamına gelir.

Son olarak, olaylar ve olay bağlamaları işlevlerden tamamen soyut olarak tutulur. Fonksiyonları değiştirmeden özel şeyleri bağlayabilmek istiyorum.

Bunu, eval() ile uğraşarak veya call_user_func() ile arayarak bunu yapabileceğimizi hissediyorum. Yine de emin değilim. eval()'u kullanmak zaten çok kötü görünüyor.

Soruma;

  1. PHP ile yapılabilecek bir şey var mı?
  2. OOP/OOP Prensiplerinde bir ismi var mı?
  3. Herhangi bir anlam ifade ediyor mu, yoksa kötü bir fikir mi?
+0

Sınıfları kullanmanın bütün amacı onları tekrar kullanmaktı? –

+0

Emin değilim. Bir vekil belki? –

+2

[Bağımlılık Enjeksiyonu] (http://en.wikipedia.org/wiki/Dependency_injection)? Tasarım kalıpları söz konusu olduğunda Fowler her zaman iyi bir kaynaktır. http://www.martinfowler.com/articles/injection.html. ** Değerlendirmekten kaçının **. – ficuscr

cevap

2

Evet, yapabilirsiniz. Ek açıklamalarla çalışan GO! AOP framework kullanarak AOP'u kullanabilirsiniz. Örneğin, her bir genel yöntem çağrısını günlüğe kaydetmek istediğinizde kullanabilirsiniz. Bunun gibi her işlev satırına eklemek yerine.

namespace Acme; 

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

Böyle Acme ad tüm sınıfların tüm kamu yöntemleri için bir Aspect kullanabilirsiniz:

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

Daha karmaşık görünüyor ama daha esnek.