Поймать фатальное исключение и продолжить

Я знаю, что по самому своему определению фатальное исключение должно убивать выполнение и не должно быть подавлено, но вот в чем проблема.

Я запускаю скрипт, который сбрасывает, анализирует и хранит в БД около 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 () позволяет избежать фатальной ошибки.