2011-11-27 11 views
9

Anonim işlevlerle çalıştığım nesnenin dışında anonim işlevler oluşturuyorum ve daha sonra __callStatic magic ile kullanacağı bir nesneye ekliyorum. işlevi. Üst sınıftan yöntemler içermek için eklenen kapaklar. Bu yöntemleri kapatmadan arayabilir miyim diye merak ediyorum.Anonim İşlev/Kapama ve self :: :: statik ::

Şu anda bu hatayı alıyorum:

EmptyObject::addMethod('open', function(){ 
    if (static::_hasAdapter(get_class(), __FUNCTION__)) 
      return self::_callAdapter(get_class(), __FUNCTION__, $details); 

    echo '<p>You have mail!</p>'; 
}); 

bu hatayı atar:

Fatal error: Cannot access static:: when no class scope is active in

Ve

//Add the functions 
EmptyObject::addMethod('open', function(){ 
    if (EmptyObject::_hasAdapter('EmptyObject', __FUNCTION__)) 
      return EmptyObject::_callAdapter('EmptyObject', __FUNCTION__, $details); 

    echo '<p>You have mail!</p>'; 
}); 

atmak bu hatayı yöntemi korunduğu için

Fatal error: Uncaught exception 'BadMethodCallException' with message 'Method '_hasAdapter' was not found in class EmptyObject'

+0

Eski php .. ben yöntemi herkese açmadan Yukarıdaki başarmak nasıl ardından –

cevap

3

Closures, bir nedenden dolayı böyle çağrılır. Tanımladıkları kapsamı "kapatıyorlar". Onlar, kapsamlarını yapıştırıldıkları yerden alabilecek kod blokları değildir.

+0

mantıklı anonimous işlevinde ':: statik' görüyorum ama olabilir? Javascript'te, yerel bir değişkendeki işleve bir referansı kaydedip kapağın içinde aramanız gerekir. Bunu PHP'de nasıl yapıyorsunuz? –

+0

Kapsamın JavaScript ve PHP'de çalıştığı yol çok farklı. PHP'nin harici kapsamının işlevler içinde nasıl görünmeyeceğinden başlayarak, JavaScript'in hangi işlevin yürütüleceği alanını nasıl değiştirebileceğinizi bitebilirsiniz. Başka bir deyişle: PHP böyle bir metaprogramlama için uygun değildir. Belki de Reflection uzantısı ile bir şeyler yapabilirsin, ama bundan emin değilim. Başka bir yol muhtemelen değerlendirmeyi kullanıyor olabilir, ancak bunun kendi dezavantajları vardır. – Mchl

13

Sen

abstract class EmptyObject 
{ 
    protected static $methods = array(); 

    final public static function __callStatic($name, $arguments) 
    { 
     return call_user_func(self::$methods[$name], $arguments); 
    } 

    final public static function addMethod($name, $fn) 
    { 
     self::$methods[$name] = Closure::bind($fn, NULL, __CLASS__); 
    } 

    final protected static function protectedMethod() 
    { 
     echo __METHOD__ . " was called" . PHP_EOL; 
    } 
} 

Şimdi EmptyObject :: addMethod (geçirilen herhangi anonim fonksiyonu) EmptyObject sınıfı

kapsamında çalışacaktır Closure::bind() (= 5.4.0> PHP) kullanarak bunu başarabilirsiniz
EmptyObject::addMethod("test", function() 
{ 
    self::protectedMethod(); 
}); 


// will output: 
// EmptyObject::protectedMethod was called 

EmptyObject::test(); 
+1

Geç statik bağlama durumunda '__CLASS__' argümanını çıkarmalı veya ('varsayılan', 'varsayılan' olarak ayarlanmalıdır). –

+0

Bu harika! – Sean256

12

Sınıf adını saklayın ve use aracılığıyla kapamaya aktarın. Herhangi bir kamu statik yöntemini çağırabilir veya genel statik özellikleri veya sabitleri bu şekilde yakalayabilirsiniz. Kapanış farklı bir içeriğe aktarılırsa, oluşturulduğunda $class için doğru değere geçtiği sürece çalışmaya devam eder. php 5.3 için çalışır: 5.5.9 yılında

class test { 
    public static function callMe() { echo 'call me '; } 

    public static function runTest() { 
     $class = __CLASS__; 
     $call = function() use ($class) { 
      $class::callMe(); 
     }; 
     $call(); 
    } 
} 
test::runTest();