从数组中调用方法和闭包


Calling methods and closures from an array

在JavaScript中,您可以执行以下操作:

var Module = (function () {
    var functions = [method1, method2]; // array of functions to execute
    function method1 () {
        console.log('calling method1');
    }
    function method2 () {
        console.log('calling method2');
    }
    function method3 () {
        console.log('calling method3');  // not called
    }
    function add (fn) {
        functions.push(fn); // add new function to the array
    }
    function printt () {
        for (var i in functions) functions[i](); // execute functions in the array
    }
    return {
        add: add,
        printt: printt
    };
})();
Module.add(function () {
    console.log('calling anonymous function');  
});
Module.printt();
// calling method1
// calling method2
// calling anonymous function

是否可以在PHP中执行类似的操作,将要执行的(1)方法存储在一个数组中,并将新的函数/方法添加到数组中,以便在运行printt方法时执行数组中的所有函数?

class Module {
    protected $functions = [];
    public function __construct () {
        // ?
    }
    protected function method1 () {
        echo 'calling method1';
    }
    protected function method2 () {
        echo 'calling method2';
    }
    protected function method3 () {
        echo 'calling method3';
    }
    public function add ($fn) {
        $this->functions[] = $fn;
    }
    public function printt () {
        foreach ($this->functions as $fn)  $fn();
    }
}
$module = new Module();
$module->add(function () {
    echo 'calling anonymous function';
});
$module->printt();

检查is_callable()的闭包和method_exists()的对象方法。

class Module {
    protected $functions = ['method1', 'method2'];
    // ...
    public function printt () {
        foreach ($this->functions as $fn) {
            if ( is_callable( $fn ) ) {
                $fn();
            } elseif ( method_exists( $this, $fn ) ) {
                $this->$fn();
            }
        }
    }
}

与JS的区别还在于,您需要在对象中通过$this正确引用方法。

另一种方法是将成员方法作为可调用项而不仅仅是方法名添加到函数数组中,然后使用call_user_func执行它们。

class Module {
  public function __construct() {
    $this->functions = [
      [$this, 'method1'],
      [$this, 'method2'],
    ];
  }
  // ...
  public function printt() {
    foreach($this->functions as $fn) {
      call_user_func($fn);
    }
  }
}