PHP:如何使用类函数作为回调

Smx*_*Cde 80 php oop callback

我有一个类,我想用作回调的方法.如何将它们作为参数传递?

Class MyClass {

    public function myMethod() {
        $this->processSomething(this->myCallback); // How it must be called ?
        $this->processSomething(self::myStaticCallback); // How it must be called ?
    }

    private function processSomething(callable $callback) {
        // process something...
        $callback();
    }

    private function myCallback() {
        // do something...
    }

    private static function myStaticCallback() {
        // do something...
    }   

}
Run Code Online (Sandbox Code Playgroud)

UPD:如何从static方法中做同样的事情(什么时候$this不可用)

Mik*_*ikO 111

查看callable手册以查看将函数作为回调传递的所有不同方法.我在这里复制了该手册,并根据您的场景添加了每种方法的一些示例.

可赎回


  • 一个PHP函数是由它的名字作为字符串传递.可以使用任何内置或用户定义的函数,除了语言结构,例如:array(),echo,empty(),eval(),exit(),isset(),list(),printunset().
  // Not applicable in your scenario
  $this->processSomething('some_global_php_function');
Run Code Online (Sandbox Code Playgroud)
  • 一个实例化的对象的方法为含有索引对象的数组传递0和索引方法名1.
  // Only from inside the same class
  $this->processSomething([$this, 'myCallback']);
  $this->processSomething([$this, 'myStaticCallback']);
  // From either inside or outside the same class
  $myObject->processSomething([new MyClass(), 'myCallback']);
  $myObject->processSomething([new MyClass(), 'myStaticCallback']);
Run Code Online (Sandbox Code Playgroud)
  • 通过传递类名而不是索引0处的对象,也可以传递静态类方法而无需实例化该类的对象.
  // Only from inside the same class
  $this->processSomething([__CLASS__, 'myStaticCallback']);
  // From either inside or outside the same class
  $myObject->processSomething(['\Namespace\MyClass', 'myStaticCallback']);
  $myObject->processSomething(['\Namespace\MyClass::myStaticCallback']); // PHP 5.2.3+
  $myObject->processSomething([MyClass::class, 'myStaticCallback']); // PHP 5.5.0+
Run Code Online (Sandbox Code Playgroud)
  • 除了常见的用户定义函数,匿名函数也可以传递给回调参数.
  // Not applicable in your scenario unless you modify the structure
  $this->processSomething(function() {
      // process something directly here...
  });
Run Code Online (Sandbox Code Playgroud)

  • 好吧,我想我是唯一一个收到“致命错误:未捕获的类型错误:传递给 ::processSomething 的参数 1 必须可调用,给定数组”的人 (9认同)
  • 米科,感谢您的回复!我知道这不是最初的问题,但是如何从 _static_ 方法(​​没有 $this 的地方)调用静态方法,并将静态方法作为参数? (2认同)
  • 你忘了提一下[`__invoke`](http://php.net/manual/en/language.oop5.magic.php#object.invoke)魔法. (2认同)
  • @Fleuv,那是因为您传递了超出范围的方法(受保护或私有方法到外部函数或类)。根本不是一个明显的错误消息。 (2认同)

Dha*_*man 36

从 PHP 8.1 开始,我们现在拥有一流的 callables。他们使用语法$callable = functionName(...). 这三个点是语法的一部分,而不是遗漏。

您可以使用新语法创建可调用的类方法。

Class MyClass {
    
    public function myMethod() {
        // first-class callables
        $this->processSomething($this->myCallback(...));
        $this->processSomething(self::myStaticCallback(...));
    }

    private function processSomething(callable $callback) {
        // Process something...
        $callback();
    }

    private function myCallback() {
        // Do something...
    }

    private static function myStaticCallback() {
        // Do something...
    }   
    
}
Run Code Online (Sandbox Code Playgroud)

这三个点不是参数的省略/占位符。它们是创建可调用对象的特殊语法。如果该方法不接受任何参数,则语法保持不变。


Ban*_*lla 9

从5.3开始,你可以用更优雅的方式编写它,我仍然试图找出它是否可以减少更多

$this->processSomething(function() {
    $this->myCallback();
});
Run Code Online (Sandbox Code Playgroud)

  • 从 PHP 5.6 开始,您可以使用可变参数函数和参数解包: `$this->processSomething(function(...$args) { $this->myCallback(...$args); });` (6认同)
  • 这可能更优雅,但你通过添加对匿名函数的不必要调用来增加开销,匿名函数只调用**实际的**回调......如果`myCallback`需要5个参数怎么办?你必须在那堂课中写下这些论点4次!我同意匿名函数作为回调很好,但是如果您在匿名函数内部编写代码*,而不仅仅包括对另一个函数的调用... (4认同)
  • 赞成这个。是的,它可以更优雅: `$this->processSomething($this->myCallback());` 而 `myCallback()` 应该返回一个匿名函数。这比将方法名称作为字符串传递更易于维护。 (2认同)

小智 6

您还可以使用call_user_func()指定回调:

public function myMethod() {

    call_user_func(array($this, 'myCallback'));
}

private function myCallback() {
    // do something...
}
Run Code Online (Sandbox Code Playgroud)