Я знаю, что по самому своему определению фатальное исключение должно убивать выполнение и не должно быть подавлено, но вот в чем проблема.
Я запускаю скрипт, который сбрасывает, анализирует и хранит в БД около 10 000 страниц. Это занимает пару часов, и в редких случаях (1 из 1000) страница не выполняет синтаксический анализ и генерирует фатальное исключение.
В настоящее время я делаю это:
for ($i=0;$i<$count;$i++) { $classObject = $classObjects[$i]; echo $i . " : " . memory_get_usage(true) . "\n"; $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap); $class = $parser->parseClassInfo($classDOM); $dbmanager->storeClassInfo($class); unset($classDOM,$class,$classObject); }
Могу ли я сделать что-то вроде
for ($i=0;$i<$count;$i++) { $classObject = $classObjects[$i]; echo $i . " : " . memory_get_usage(true) . "\n"; try { $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap); $class = $parser->parseClassInfo($classDOM); $dbmanager->storeClassInfo($class); unset($classDOM,$class,$classObject); } catch (Exception $e) { //log the error here continue; } }
сfor ($i=0;$i<$count;$i++) { $classObject = $classObjects[$i]; echo $i . " : " . memory_get_usage(true) . "\n"; try { $classDOM = $scraper->scrapeClassInfo($classObject,$termMap,$subjectMap); $class = $parser->parseClassInfo($classDOM); $dbmanager->storeClassInfo($class); unset($classDOM,$class,$classObject); } catch (Exception $e) { //log the error here continue; } }
Вышеприведенный код не работает для fatal exceptions
.
Можно ли сделать что-то вроде этого: если я переместил основной цикл в метод, а затем вызовет метод из register_shutdown_function
?
Как это:
function do($start) { for($i=$start;$i<$count;$i++) { //do stuff here } } register_shutdown_function('shutdown'); function shutdown() { do(); }
Это сообщение, которое выводится, когда выполнение останавливается:
Fatal error: Call to a member function find() on a non-object in ...
Я ожидаю это выше, когда страница не анализируется методом, который я использую. Я в порядке, просто пропуская эту страницу и перейдя к следующей итерации цикла.
Фатальные ошибки являются фатальными и прекращают выполнение. Нет никакого способа обойти это, если произойдет фатальная ошибка. Однако, ваша ошибка:
Неустранимая ошибка: вызов функции-члена find () для не-объекта в …
полностью предотвращается. Просто добавьте проверку, чтобы убедиться, что у вас есть экземпляр правильного объекта, а если нет, обработайте ошибку:
if ($foo instanceof SomeObject) { $foo->find(...); } else { // something went wrong }
Во-первых, существует четкое различие между исключениями и ошибками . То, с чем вы столкнулись, является ошибкой , а не исключением. На основе вашего сообщения и кода, который вы опубликовали, проблема связана с тем, что вы не задали в своем вопросе. Какую переменную вы пытаетесь вызвать find()
? Ну, эта переменная не является объектом. Невозможно уловить фатальные ошибки и игнорировать их, вы должны найти, где вы вызываете find()
на не-объект, и исправить его.
Мне кажется, что единственный возможный способ «поймать» фальтальную ошибку – это зарегистрировать функцию выключения. Не забудьте добавить все (или, возможно, группы) запросов в транзакции и, возможно, отбросить их обратно, если что-то не удастся, просто для обеспечения согласованности.
У меня была аналогичная проблема, и я обнаружил, что использование вызова is_object () перед вызовом find () позволяет избежать фатальной ошибки.