На текущий момент мой ответ изменился, когда я закончил работу с пачкой поставщиков и постоянно меняющимися условиями - сегодня по цене, потом по сортировки, завтра еще по чем...
1. Не использовать for {}, если есть map()
2. В map возвращать array(1,msg,data)
3. Если map вложенный или родительский - в ответ отправляется data, а ошибки собираются в err[]
Таким образом где-то так:
function mapfunc($item) {
return array(null, null, array(
"stdout" => $item,
"stderr" => $foobar,
)
);
}
Это в соответствии с договоренностью о возврате массива array(errcode, msg, data).
По итогу после map() для какой-то коллекции на выходе получим коллекцию из отчетов.
Если с элементами после отчета нужно что-то делать - собираем их из отчетов, сами отчеты сохраняем для будущего вывода. С элементами повторяем процедуру.
Если у нас (редко бывает но все же) коллекция из коллекций, и нужен рекурсивный обход - тот же алгоритм - прошлись, собрали отчеты, из отчетов получили данные, с данными дальше работаем.
Главное не забывать, что данные могут быть вручную добавлены из функции map() и потому лучше те данные что были совать отдельным ключом, а те что по ходу подсовываются для информации об ошибке - отдельным.
Это примерно как концепция отдельного процесса, когда у него есть поток вывода сервисный, для ошибок, а есть поток вывода пользовательский - для результата.
Такой подход будет универсальным и для работы с ajax запросами, и для работы с коллекциями, и при загрузке в базу данных поочередно, и для очередей запросов - очень удобно, если освоить функцию типа _pluck, чтобы быстро отделять данные от отчетов.
Но особо упертые могут делать два разных map() - один для отчетов по ошибкам, другой - с заглушенными ошибками и просто для данных - на выходе получится массив из null и корректных данных.
Отдельная реализация может быть даже такая:
$rep = array();
$data = array_map(function ($row) use (&$rep) {
$bad = false;
if ($bad):
$rep["bad"] = array(1, "msg", array("foo" => $foo, "bar" => $bar));
return null;
else:
$rep["good"] = array(null, "OK", array("foo" => $foo, "bar" => $bar));
return $row;
endif;
});
Это все к тому, что ХОРОШЕЕ приложение - НЕ ИМЕЕТ ошибок. А с точки зрения логики приложение НЕ МОЖЕТ не иметь ошибок, поскольку нельзя гарантировать идеально правильного человека. Смысл ошибки сводится в конечном итоге к вине пользователя. Если пользователь сотворил беду и сам хочет ошибку - он должен ее получить, а если он ничего не делал толком, а ошибка произошла - то ее не должно было произойти.
Но показывать то их нельзя, поэтому для главного модуля это warning, а для конечного этапа это exception. А ошибка одна и та же.