【问题标题】:How to use class methods as callbacksPHP:如何使用类函数作为回调[重复]
【发布时间】:2015-05-11 07:51:05
【问题描述】:

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

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...
    }   

}

UPD:如何通过static 方法执行相同操作(当$this 不可用时)

【问题讨论】:

  • 我建议关闭 the other 作为这个骗子,然后重新提出这个问题,因为这个问题更加最新和详细。

标签: php oop callback


【解决方案1】:

查看callable manual 以查看将函数作为回调传递的所有不同方式。我在此处复制了该手册,并根据您的情况添加了每种方法的一些示例。

可调用


  • PHP 函数 通过其名称作为字符串传递。可以使用任何内置或用户定义的函数,但语言结构除外,例如:array()echoempty()eval()exit()isset()list()打印 em> 或 unset().
  // Not applicable in your scenario
  $this->processSomething('some_global_php_function');

  • 实例化对象的方法作为数组传递,其中包含索引 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']);

  • 静态类方法也可以在不实例化该类的对象的情况下传递,方法是传递类名而不是索引 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+

  • 除了常用的用户自定义函数外,匿名函数也可以传递给回调参数。
  // Not applicable in your scenario unless you modify the structure
  $this->processSomething(function() {
      // process something directly here...
  });

【讨论】:

  • MikO,感谢您的回复!我知道这不是最初的问题,但是如何使用静态方法作为 static 方法的参数调用静态方法(没有 $this)?
  • 到目前为止,我能想到的最佳解决方案是self::processSomething([__CLASS__, 'callback']);
  • 你忘了提到__invoke魔法方法。
  • 好吧,我想我是唯一获得Fatal error: Uncaught TypeError: Argument 1 passed to ::processSomething must be callable, array given的人
  • @Fleuv,那是因为你传递了一个超出范围的方法(一个受保护的或私有的方法到一个外部函数或类)。根本不是明显的错误消息。
【解决方案2】:

从 5.3 开始有一种更优雅的方式可以编写它,我仍在尝试找出是否可以进一步减少它

$this->processSomething(function() {
    $this->myCallback();
});

【讨论】:

  • 这可能更优雅,但是您通过添加对匿名函数的不必要调用来增加开销,该函数只是调用 actual 回调......如果@ 987654322@ 需要 5 个参数?你必须在那堂课上写 4 次这些论点!我同意匿名函数作为回调很好,但是如果您在匿名函数内部编写代码,而不仅仅是对另一个函数的调用......
  • 你说得对,我没有考虑过传递论点。但是除非我读错了,否则您指定的方式也无法通过争论。
  • 对此表示赞同。是的,它可以更优雅:$this->processSomething($this->myCallback());myCallback() 应该返回一个匿名函数。这比将方法名称作为字符串传递更易于维护。
  • 从 PHP 5.6 开始,您可以使用可变参数函数和参数解包:$this->processSomething(function(...$args) { $this->myCallback(...$args); });
  • 没有更好的方法来传递现有函数吗?我不喜欢这样做的另一个例子:假设 processSomething 验证给定的参数,如果第一个参数不是有效的回调,则抛出异常。如果你像上面那样将调用包装在一个新的闭包中,它将首先通过,然后在回调函数实际执行时爆炸。这使得调试变得非常困难,因为您跳过了出于某种原因实施的验证。
【解决方案3】:

你也可以使用 call_user_func() 来指定回调:

public function myMethod() {

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

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

【讨论】:

    猜你喜欢
    • 2013-10-20
    • 2011-04-19
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多