Storing a Closure Function in a Class Property in PHP

后端 未结 6 1020
清歌不尽
清歌不尽 2021-01-21 07:37

ok I do have the code below

bar();
       }
    }

    $mee         


        
相关标签:
6条回答
  • 2021-01-21 08:03

    You need to exploit some magic functionality of PHP (__call) to make use of that. Extend from Extendable for example:

    class Extendable {
        static function import($context) {
            $self = new static();
            while (is_callable($context)) $context = $context($self);
            if (is_array($context) || is_object($context) || is_a($context, 'Traversable')) {
                foreach($context as $key => $value)
                    $self->$key = &$value; # preserve keys if
            }
            return $self;
        }
        public function __call($name, $args) {
            if (isset($this->$name) && is_callable($this->$name)) {
                return call_user_func_array($this->$name, $args);
            }
            throw new BadFunctionCallException(sprintf('Undefined function %s.', $name));
        }
    }
    

    And you can do the job. It's not that nice. Background and examples are in one of my blog posts:

    • PHP: Extending stdClass with Closures (plus Visitor)

    You can naturally implement that magic functionality your own, too.

    0 讨论(0)
  • 2021-01-21 08:09

    PHP is not a prototype based language hence you cannot redefine functions

    0 讨论(0)
  • 2021-01-21 08:12

    Use __call to catch all non-defined methods and then look up the closure and invoke it. Take a look at my post on this SitePoint thread.

    0 讨论(0)
  • 2021-01-21 08:14

    Use call_user_func() function:

    <?php
        class foo{
           public $bar = NULL;
    
           public function boo(){
              call_user_func($this->bar);
           }
        }
    
        $mee = new foo();
    
        //save a closure function on the property
        $mee->bar = function(){
            echo 'hahaha';
        };
    
        //invoke the closure function by using a class method
        $mee->boo();
    

    This will display "ahahah"

    Hope it helps.

    0 讨论(0)
  • 2021-01-21 08:16

    You will not be able to do that.

    Take for example this code:

    class T {
      function foo() {
        echo 'T::foo';
      }
    }
    
    $t = new T;
    $t->foo = function() {
      echo 'Closure::foo';
    };
    $t->foo();
    

    It works fine on PHP 5.4.6 and/or PHP 5.3.16, however it will result in T::foo getting printed.

    This happens because methods, in PHP, are not modifiable class properties, as they are for example in javascript.

    However,

    $foo = $t->foo;
    $foo();
    

    will print Closure::foo as expected.

    0 讨论(0)
  • 2021-01-21 08:21

    Your example code at codepad.org does not work because codepad.org uses PHP 5.2.5, and closure support was only added in 5.3.

    However, your code will also not work in a PHP version that supports closures, although you will get a different error: http://codepad.viper-7.com/Ob0bH5

    This is a limitation of PHP at present. $obj->member() looks for a method named member and will not look at properties to see if they are callable. It is, frankly, annoying.

    The only way I am aware of to make this work without call_user_func()/call_user_func_array() is:

    public function boo() {
       $func = $this->bar;
       $func();
    }
    
    0 讨论(0)
提交回复
热议问题