Today's anonymous submitter sends us some PHP exception logging code. This particular code shows a surprising understanding of some clever PHP tricks. Unfortunately, everything about it is still wrong.

try {
    // do stuff that might throw an exception
} catch (Throwable $th) {
    ob_start(); // start buffer capture
    
    echo($th->getMessage()); // dump the values
    var_dump($th); // dump the values
    $ob = ob_get_contents(); // put the buffer into a variable
    
    ob_end_clean(); // end capture
    
    error_log($ob); 
}

The purpose of this code is to log the exception message, and a string representation of the thrown exception, including its key properties. Now, a normal developer would just take advantage of the Throwable's built in string conversion to get that information. But for whatever reason, this developer didn't want a simple, short, human-readable version. They opted to use var_dump, a handy PHP debugging function which dumps an object's properties to the output buffer.

Which, by default, the output buffer is the page this PHP script is rendering. Which is what all the ob_ calls are about: they create a temporary output buffer, write all further output to that, and then fetch the contents of the buffer as a string.

Once they have that string, they can then error_log it.

None of that is necessary. But in this codebase, it appears in about 70% of the exception handlers. Some of the remaining 25% do something more sane. Some of them just swallow the exception or rethrow it.

It's worth noting that the output of just to-stringing the throwable isn't formatted the exact same way as the var_dump version- the to-string version is more readable, while the var_dump looks something more like this:

messageobject(Exception)#1 (7) {
  ["message":protected]=>
  string(7) "message"
  ["string":"Exception":private]=>
  string(0) ""
  ["code":protected]=>
  int(0)
  ["file":protected]=>
  string(63) "/home/user/scripts/code.php"
  ["line":protected]=>
  int(4)
  ["trace":"Exception":private]=>
  array(0) {
  }
  ["previous":"Exception":private]=>
  NULL
}

The additional problem is that nobody wanted the logs to look like that, nobody liked reading logging messages looking that way, and everyone wished the output was more compact and relevant. Yet this was the solution.

Our submitter adds:

TRWTF might as well be not using an actual Exception Handler and Logger to handle this, though, with this being WordPress…

[Advertisement] Utilize BuildMaster to release your software with confidence, at the pace your business demands. Download today!