Перерыв array_walk из анонимной функции

Есть ли способ остановить array_walk внутри анонимной функции?

Вот пример кода (который работает), чтобы показать, что я имею в виду, который проверяет, имеет ли массив только числовые значения.

$valid = true;
array_walk($parent, function ($value) use (&$valid) {
    if (!is_numeric($value)) {
        $valid = false;
    }
});

return $valid ? 'Valid' : 'Invalid';

Если у меня есть достаточно большой массив, и первая запись недействительна, остальные (избыточные) проверки все еще выполняются, поэтому я хотел бы остановить выполнение.

Использование break/continue не работает (ошибка: Fatal error: Cannot break/continue 1 level in ...).

Примечание: Я не хочу переписывать код, я просто хочу знать IF. Это возможно.

Ответы

Ответ 1

Как было сказано, теоретически это возможно, но я бы посоветовал это сделать. Здесь, как использовать Exception для выхода из array_walk.

<?php
$isValid = false;

$array = range(1, 5);

try {
    array_walk($array, function($value) {
        $isAMagicNumber = 3 === $value;
        if ($isAMagicNumber) {
            throw new Exception;
        } 
    });
}catch(Exception $exception) {
    $isValid = true;
}

var_dump($isValid);

/*
    bool(true)
*/

Ответ 2

Вы можете поместить статический флаг внутри анонимной функции:

array_walk($ary, function($item) {
    static $done = false;
    if($done) {
        return;
    }

    // … your code

    if($myBreakCondition) {
        $done = true;
        return;
    }
});

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

В вашем случае код будет выглядеть следующим образом:

$valid = true;
array_walk($parent, function($value) use(&$valid) {
    static $done = false;
    if($done) {
        return;
    }

    if(!is_numeric($value)) {
        $valid = false;
        $done = true;
        return;
    }
});
return $valid ? 'Valid' : 'Invalid';

Но на самом деле это не будет большой разницей, если бы не было "перерыва" вообще. Для каждого недопустимого значения будет назначаться только "ложь", что не имеет значения, поскольку результат будет по-прежнему ложным. Возможно, было бы еще более эффективным, чтобы моя статическая переменная читала.

Лично в вашем случае я бы использовал вместо array_filter:

$valid = count(array_filter($parent, 'is_numeric')) == count($parent);

или просто

$valid = array_filter($parent, 'is_numeric')) == $parent;

Если все значения в массиве $parent являются числовыми, все они будут присутствовать после фильтрации. С другой стороны, любое нечисловое значение в массиве повлияет на содержимое (уменьшение количества элементов) в фильтрованном массиве, и сравнение даст ложь.