Variable Assignment, Exception Handling, and Destructors in PHP

I had the craziest set of “bugs” the other day — well, that was until I realized they weren’t bugs. It turns out, at least in PHP, if you try to assign an object to a variable, but during the assignment, an exception is thrown, the variable keeps its original value. Oh, and the destructor fires immediately before anything else. I am not sure if this is true in other languages, but if it is, please let me know. 🙂

Not sure what the hell I’m talking about, or want to learn more about exception handling? If I get any requests in my comments, I’ll follow up on a walk-through about the topic. Same goes for destructors. Speak up or forever hold your peace.

Exceptions and Variable Assignment

So back to the problem at hand:

$connection = ‘hello’;
try {
    $connection = new Database($parameters);
    $connection->doStuff();
} catch (Exception $exception) {
    echo $exception->getMessage();
} // continue as if nothing happened
var_dump($connection);

So what’s the result when I dump $connection?

  1. If no exception is thrown anywhere, the value is the Database object.
  2. If an exception is thrown during doStuff(), the value is the Database object (as expected).
  3. If an exception is thrown in the constructor of Database, the value of $connection is “hello”.

This makes sense. During the assignment, the code is short circuited, and the object is never assigned.

In other words:

  1. new Database() is processed.
  2. During processing (the constructor), throws an error.
  3. The code exits out of the constructor and looks for a catch statement.
  4. The first catch statement found is below the assignment line.
  5. Thus not only does doStuff() never get executed, but the Database object is never assigned.
  6. The $connection variable is never modified.

The lesson I take away from this is to not throw exceptions in constructors. This is largely whey I only do property assignments during constructors and any potentially error causing stuff is tossed in an initialize() function I call later during the first operation that might require more than simple assignments. But that’s just me.

Destructors on Exceptions During Constructors

For those of you still reading, and understanding what I’m talking about, I have another point to add: destructors fire before the exception is thrown out! As in, as soon as the program sees the throw keyword and we leave the constructor, the destructor fires! I imagine this is because since the variable was never assigned, it’s just a dangling variable in memory, and thus gets cleaned up immediately.

This is probably nothing unexpected, but surely something to keep in mind if you use PHP destructors (as I was). This is relevant because I was trying to log some stuff during the destructor, even on an error. Exceptions cause text to get dumped, so I figured I would just collect the text in the destructor (from the output buffer) and then toss it in a file. Unfortunately, that didn’t work because the destructor fired way before the exception had a chance to display anything. My (broken) code looked something like this:

ob_start();
$framework = NULL;
try {
    $framework = new Framework();
    $framework->initialize();
} catch (Exception $exception) {
    echo $exception->getMessage();
}
unset($framework); // make the destructor go off

During the destructor, anything written to the output buffer (error or no error) was tossed in a file. This worked unless an exception was tossed in the Framework constructor.

Output Buffers and Destructors (tricky!)

Lastly, as a golden bonus to those still reading, the reason I manually unset the variable is because through trial and error, I discovered that at the end of a program’s execution, the output buffer is flushed (and cleaned) before variables are erased. This meant that by the time my destructor fired (when $framework got erased), the output buffer was already empty and crap was already on the client’s screen. Thus, I had to unset it manually. 🙂

I hope this helped somebody.

One thought on “Variable Assignment, Exception Handling, and Destructors in PHP”

  1. “For those of you still reading, and understanding what I’m talking about, I have another point to add: destructors fire before the exception is thrown out! As in, as soon as the program sees the throw keyword and we leave the constructor, the destructor fires! I imagine this is because since the variable was never assigned, it’s just a dangling variable in memory, and thus gets cleaned up immediately.”

    The reason the destructor fires before the exception is thrown (at least for other languages like C++) is because the exception causes a jump to a new code block and there is no guarantee that the catching code block would–or could–send you back to the throwing code block. Since it is unlikely that the catching block would do that, the destructor has to be called before the exception is thrown or anything allocated in the constructor would become a memory leak (it would never be destructed).

Comments are closed.