如何在PHP中定义不带参数的回调函数并在PHP中使用?

How to define a callback with parameters without closure and use in PHP?

在 PHP 中,为了定义回调,可以使用闭包,传递静态参数的工具是 use 指令。

class MyClass {
    public function foo($x) {
        echo $x;
    }
    public function bar() {
        $x = '123';
        $callback = function () use ($x) {
            $this->foo($x);
        };
        $callback();
    }
}

$myClass = new MyClass();
$myClass->bar();

是否可以/如何避免匿名函数,用方法代替?

class MyClass {
    public function foo($x) {
        echo $x;
    }
    public function baz() {
        $x = '567';
        // There is no function with the name create_user_func.
        // Just to show, what I'm looking for.
        $callback = create_callback([$this, 'foo'], $params = [$x]);
        $callback();
    }
}

$myClass = new MyClass();
$myClass->baz();

编辑:

一些额外的/背景信息(明确我想要实现的目标和原因 - 并避免误解):

在我的具体案例中,我需要将回调传递给框架的方法。这意味着:我不能/可能不会影响它被调用的方式。

该方法只接受回调本身,不接受回调参数。这意味着,回调必须 "know"/提供它需要的静态参数(及其值)。

正是 use 指令解决的问题。但是我的方法中有多个回调定义,而且方法越来越长。所以我想将回调的逻辑移动到单独的方法中。

有很多方法可以实现这一点。

  1. 使用辅助函数。

代码:

class MyClass {
    private $x;

    public function foo() {
        echo $this->x;
    }
    public function bar() {
        $this->x = '123';
        anon($this);
    }
}

$myClass = new MyClass();
$myClass->bar();

function anon($obj) {
    $obj->foo();
}
  1. 使用 call_user_func.

代码:

class MyClass {
    private $x;

    public function foo() {
        echo $this->x;
    }
    public function bar() {
        $this->x = '123';
        call_user_func([$this, 'foo']);
    }
}

$myClass = new MyClass();
$myClass->bar();
  1. 如果出于某种原因你不想使用成员变量,你可以通过 call_user_func_array.
  2. 传递参数

代码:

class MyClass {
    private $x;

    public function foo($x) {
        echo $x;
    }
    public function bar() {
        $x = '123';
        call_user_func_array([$this, 'foo'], [$x]);
    }
}

$myClass = new MyClass();
$myClass->bar();

But I have multiple callback definitions in my method, and the method is getting long. So I want to move the logic of the callbacks to separate methods.

这是魔术方法的完美示例__invoke()

对于您需要的每个回调,将其使用的功能和属性提取到一个新的 class 中。将代码放入新的class的__invoke()方法中,将它需要的所有属性初始化到它的__construct()中,你就可以开始了。

代码:

class MyClass {
    public function bar() {
        $x = '123';
        // Create the callback, pass the values it needs to initialize
        $callback = new ActionFoo($x);
        // Call the callback without arguments
        $callback();
    }
}

class ActionFoo {
    private $x;
    public function __construct($x) {
        $this->x = $x;
    }
    public function __invoke() {
        echo($this->x);
    }
}

$myClass = new MyClass();
$myClass->bar();

我想可以公平地说,您正在尝试模仿 Javascript 的 bind 方法。 PHP 中的问题是函数不是第一个 class 公民或对象,所以像 ->bind($x) 这样的东西是不可能的。也没有办法为 callable 传递额外的参数。所以你要把它包装在东西.

一个更可重用的方法是写一个合适的 class:

class CallbackWrapper {
    protected $callable,
              $args;

    public function __construct(callable $callable, array $args) {
        $this->callable = $callable;
        $this->args     = $args;
    }

    public function __invoke() {
        call_user_func_array($this->callable, $this->args);
    }
}

giveMeACallback(new CallbackWrapper([$this, 'foo'], [$x]));

或者你只是简化匿名函数的构造:

function make_callback(callable $callable, array $args) {
    return function () use ($callable, $args) {
        return call_user_func_array($callable, $args);
    };
}

giveMeACallback(make_callback([$this, 'foo'], [$x]));