匿名函数/闭包并使用self ::或static ::

Dev*_*xon 9 php static closures anonymous-function

我正在使用匿名函数,我在对象之外创建匿名函数,然后将其添加到稍后将与__callStatic魔术函数一起使用的对象中.要添加的闭包包含父类的方法.我想知道我是否能够从闭包中调用这些方法?

现在我收到此错误:

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

    echo '<p>You have mail!</p>';
});
Run Code Online (Sandbox Code Playgroud)

抛出此错误:

致命错误:当没有活动类范围时,无法访问static ::

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

    echo '<p>You have mail!</p>';
});
Run Code Online (Sandbox Code Playgroud)

抛出此错误,因为该方法受到保护

致命错误:在类EmptyObject中找不到带有消息'Method'ahasAdapter'的未捕获异常'BadMethodCallException'

小智 13

你可以通过使用Closure :: bind()来实现这一点(PHP> = 5.4.0)

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;
   }
}
Run Code Online (Sandbox Code Playgroud)

现在传递给EmptyObject :: addMethod()的任何匿名函数都将在EmptyObject类的范围内运行

EmptyObject::addMethod("test", function()
{
   self::protectedMethod();
});


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

EmptyObject::test();
Run Code Online (Sandbox Code Playgroud)


小智 12

只需存储类名并将其传递给闭包use.您可以调用任何公共静态方法或以这种方式获取公共静态属性或常量.如果将闭包传递给不同的上下文,只要$class在创建时将正确的值传递给它,它仍然可以工作.适用于php 5.3:

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

    public static function runTest() {
        $class = __CLASS__;
        $call = function() use ($class) {
            $class::callMe();   
        };
        $call();
    }
}
test::runTest();
Run Code Online (Sandbox Code Playgroud)


Mch*_*chl 3

闭包被这样称呼是有原因的。它们“封闭”了它们定义的范围。它们不仅仅是可以从粘贴到的位置获取范围的代码块。