函数的参数必须是可调用的,但给出的是数组。

30

我正在尝试对集合中的每个元素运行一个方法。它是同一类中存在的对象方法:

protected function doSomething()
{
    $discoveries = $this->findSomething();
    $discoveries->each([$this, 'doSomethingElse']);
}

protected function doSomethingElse($element)
{
    $element->bar();
    // And some more
}
如果我在对Collection::each的调用之前添加检查is_callable([$this, 'doSomethingElse']),它会返回true,所以显然是可调用的。然而,调用本身会抛出一个异常:

Type error: Argument 1 passed to Illuminate\Support\Collection::each() must be callable, array given, called in ---.php on line 46

可以在这里找到试图调用的方法 here
我通过只传递一个闭包来绕过这个问题,闭包本身只是调用那个函数,但这肯定是一种更干净的解决方案,我找不到为什么会引发错误。

2
@bxN5 这不应该是一个函数,而应该是一个“可调用对象”。is_callable返回true,因此我会认为当传递给期望一个“可调用对象”的函数时它可以工作。 - padarom
3
请将doSomethingElse()声明为public。在我看来,我认为each()是在上下文中调用collection类,该类无法访问其他类中受保护的函数。 - dparoli
我怀疑findSomething或者doSomethingElse抛出了异常。根据我的有限经验,这个错误信息可能是一个误导。 - Michael Easter
可能是这样,但与此同时,我用不同的方法解决了它,也记不清楚我在哪里使用过它,因此无法验证。 - padarom
4个回答

47

将您的回调方法的可见性更改为公共(public)。

protected function doSomething()
{
    $discoveries = $this->findSomething();
    $discoveries->each([$this, 'doSomethingElse']);
}

public function doSomethingElse($element)
{
    $element->bar();
    // And some more
}

29

自 PHP 7.1 开始,您可以将函数声明为 protected。现在您可以编写:

protected function doSomething()
{
    $discoveries = $this->findSomething();
    $discoveries->each(\Closure::fromCallable([$this, 'doSomethingElse']));
}

protected function doSomethingElse($element)
{
    $element->bar();
    // And some more
}


3

带回调函数的函数

public function foo(callable $callback){ 
    $callback('something') 
} 

回调函数的命名函数

public function do($something) { 
   // 
} 

结果

foo(function ($something) { 
        // 
})

或者调用命名函数

foo(\Closure::fromCallable([$this, 'do']))

或者
foo(this->do(...))

-1

PHP >= 5.4

我无法重现您的错误,但我的猜测是您应该在回调数组中使用$discoveries而不是$this,像这样:

$discoveries->each([$discoveries, 'doSomethingElse']);

尽管$discoveries$this属于同一类,因此可以访问彼此的受保护和私有方法,但类型提示功能可能不会检查回调数组中的对象是否与当前类相同。然而,is_callable()方法将检查这一点,这可能解释了为什么在each()方法内部调用它时返回true。

PHP < 5.4

没有名为callable的类型,因此当您将其用作类型提示时,它是指一个名为callable请参见此答案。


1
我没有指定我使用的Laravel版本,但它需要PHP 5.6+,所以<5.4的情况不是问题。然而,我会尝试另一种情况。 - padarom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接