Вызываемый метод не как массив

Обычно в PHP, если у вас есть метод bar класса Foo и вы хотели бы передать его как вызываемый, вы используете что-то вроде

$foo = new Foo();
$callable = [$foo, 'bar'];

Недостатком этого является то, что is_array($callable) оценивает true,

Есть ли другой возможный способ передать метод класса как вызываемый так, чтобы is_array($callable) возвращается false?

9

Решение

Да, есть … хотя это ужасный, ужасный хак

$foo = new Foo();

function makeCallable($instance, $method)
{
return function() use ($instance, $method) {
return $instance->{$method}();//use func_get_args + call_user_func_array to support arguments
};
}

Тогда вы можете использовать:

$callable = makeCallable($foo, 'bar');
var_dump(is_array($callable));//false

Недостатком является то, что:

var_dump($callbale instanceof Closure);//true

По сути, не обращайте внимания на тот факт, что ваш вызываемый объект также является массивом, а просто используйте подсказки типов во всей базе кода:

function foobar(callable $action)
{
return call_user_func($action);
}

Это должно работать просто отлично.

От того, почему вы чувствуете, что текущий вызываемый массив является недостатком: я понимаю, почему вы чувствуете, что это не очень хорошая вещь. Никто не должен знать, что конкретная вызываемая конструкция — это массив, или строка, или анонимная функция (которая на самом деле является экземпляром Closure класс — еще одна деталь реализации, которую вы, возможно, не захотите передавать). Но это именно потому, что вызываемые конструкции бывают разных форм, callable подсказка типа существует: код, который вы пишете, который требует вызываемого объекта, не должен заботиться о том, как реализован этот вызываемый объект, ему просто нужно знать, что он может вызвать эту часть информации:

function handleEvent(callable $action, array $args = null)
{
if ($args) {
return call_user_func_array($action, $args);
}
return call_user_fun($action);
}

Мне не нужно проверять, если $action это строка (как 'strtolower', Closure экземпляр или массив) я просто знать Я могу назвать это

10

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

Функции и методы не первоклассные граждане в PHP, т.е. они не могут быть назначены переменной, не имеют типа и т. д.

callable на самом деле не тип, is_callable так же хорошо как callable подсказка типа просто проверяет, может ли быть что-то используется как функция. Это может быть:

  • массив [class, method] для статического метода
  • массив [object, method] для метода экземпляра
  • строка для функции
  • Closure пример
  • объект, который реализует магический метод __invoke()

Как видите, все эти значения на самом деле имеют другой тип и просто могут быть вызваны. Не существует такого понятия, как «чистый» вызов, который не имеет другого типа.

4