Аргумент, переданный функции, должен быть вызываемым, массив задан

Я пытаюсь запустить метод для каждого элемента внутри коллекции. Это объектный метод, находящийся в том же классе:

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, поэтому, по-видимому, он может быть вызван. Однако сам вызов вызывает исключение:

Ошибка типа: аргумент 1 передан в иллюстрацию\Поддержка\Коллекция:: each() необходимо    быть вызванным, массив задан, вызывается в ---. php в строке 46

Метод, который нужно вызвать, можно найти здесь.

Я обойду это, просто передав закрытие, которое сам просто вызывает эту функцию, но это, безусловно, намного более чистое решение, и я не могу понять, почему он выдает ошибку.

Ответ 1

Измените видимость метода обратного вызова для общего доступа.

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

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

Ответ 2

Начиная с PHP 7.1 вы можете оставить свою функцию защищенной. Теперь вы можете написать:

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

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

Источник

Ответ 3

PHP >= 5.4

Я не смог воспроизвести вашу ошибку, но я предполагаю, что в массиве обратного вызова вы должны использовать $discoveries вместо $this, например:

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

Несмотря на то, что $discoveries и $this имеют один и тот же класс и, следовательно, могут обращаться к другим защищенным и закрытым методам, функция подсказки типа может не проверять, что объект в массиве обратного вызова является тем же классом, что и текущий класс. Тем не менее, метод is_callable() проверяет это, что может объяснить, почему оно возвращает true, когда вы вызываете его из метода each().

PHP < 5,4

Нет типа с именем callable, поэтому, когда вы используете его как подсказку типа, он ссылается на класс с именем callable. См. этот ответ.