лямбда — Как определить обратный вызов с параметрами без закрытия и использования в 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();

РЕДАКТИРОВАТЬ:

Некоторая дополнительная информация / справочная информация (чтобы прояснить, чего я хочу достичь и почему — и чтобы избежать недоразумений):

В моем конкретном случае мне нужно передать обратный вызов в метод фреймворка. Это означает: я не могу / не могу влиять на то, как он вызывается.

Метод принимает только сам обратный вызов, без аргументов для обратного вызова. Это означает, что обратный вызов должен «знать» / предоставлять статические параметры (и их значения), в которых он нуждается.

Это именно то, что use Директива решает. Но у меня есть несколько определений обратного вызова в моем методе, и метод становится длинным. Поэтому я хочу перенести логику обратных вызовов в отдельные методы.

1

Решение

Но у меня есть несколько определений обратного вызова в моем методе, и метод становится длинным. Поэтому я хочу перенести логику обратных вызовов в отдельные методы.

Это идеальный пример для магического метода __invoke()

Для каждого необходимого обратного вызова извлеките функциональность и свойства, которые он использует, в новый класс. Поместите код в __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();
1

Другие решения

Я думаю, будет справедливо сказать, что вы пытаетесь подражать Javascript bind метод. Проблема с этим в PHP заключается в том, что функции не являются гражданами или объектами первого класса, поэтому что-то вроде ->bind($x) это невозможно. Там также нет способа передать дополнительные параметры для callable. Итак, вы собираетесь иметь обернуть что-то.

Более пригодный для повторного использования метод — написать соответствующий класс:

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]));
1

Есть много способов достичь этого.

  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,

Код:

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();
0
По вопросам рекламы [email protected]