Есть ли способ остановить 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 ...
).
Примечание. Я не хочу переписывать код, я просто хочу знать, что это возможно.
Как было сказано, теоретически это возможно, но я бы посоветовал это сделать. Вот как использовать 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) */
Вы можете поместить статический флаг внутри анонимной функции:
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
массиве $parent
являются числовыми, все они будут присутствовать после фильтрации. С другой стороны, любое нечисловое значение в массиве будет влиять на содержимое (уменьшение количества элементов) в фильтрованном массиве, и сравнение даст false.