Home » Php » php – Catch a fatal exception and continue

php – Catch a fatal exception and continue

Posted by: admin July 12, 2020 Leave a comment

Questions:

I know, that by its very definition, a fatal exception is supposed to kill the execution, and should not be suppressed, but here’s the issue.

I’m running a script that scrapes, parses and stores in a DB about 10,000 pages. This takes a couple of hours, and in rare cases (1 in 1000) a page fails parsing and throws a fatal exception.

Currently, I’m doing this:

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);           
        }        

Can I do something like

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;
    }
}

The code above doesn’t work for fatal exceptions.

Would it be possible to do something like this:
If I moved the main loop into a method, and then call the method from register_shutdown_function ?

Like this:

function do($start)
{
   for($i=$start;$i<$count;$i++)
   {
      //do stuff here
   }
}

register_shutdown_function('shutdown');

function shutdown()
{ 
   do();
}

This is the message that is output when execution stops:

Fatal error:  Call to a member function find() on a non-object in ...

I expect this above message when a page isn’t parse-able by the method I am using. I’m fine with just skipping that page and moving on to the next iteration of the loop.

How to&Answers:

Fatal errors are fatal and terminate execution. There is no way around this if a fatal error occurs. However, your error:

Fatal error: Call to a member function find() on a non-object in …

is entirely preventable. Just add a check to make sure you have an instance of the correct object, and if not, handle the error:

if ($foo instanceof SomeObject) {
    $foo->find(...);
} else {
    // something went wrong
}

Answer:

First, there is a distinct difference between exceptions and errors. What you encountered is an error, not an exception. Based on your message and the code you posted the problem is with something you haven’t put into your question. What variable are you trying to call find() on? Well, that variable isn’t an object. There is no way to trap fatal errors and ignore it, you must go find where you are calling find() on a non-object and fix it.

Answer:

Seems to me like the only possible way to “catch” a faltal error is with the registering a shutdown function. Remember to add all (or maybe groups of) queries into transactions and maybe roll them back if something fails, just to ensure consistency.

Answer:

I have had a similar problem to this, and I found that using a is_object() call before the find() call allows you to avoid the fatal error.