Permission Denied in the PHP Destructor and the Current Folder

I learned something new today, so I’m going to share two cool things with you.

  1. File access is screwed up during a destructor call in PHP. I will show you how to get around this.
  2. How to create a universal absolute path variable that refers to the current folder you are in.

For the application I was working on today, we needed to add logging. This was a quick and dirty log that would (append) dump whatever was on the page into a file. I was working in a framework I wrote, where each page is actually a class. Neat, but not really necessary to understand the problem.

Here’s the code:

function __destruct() {
    $handle = fopen(CURRENT FOLDER . 'no_sync.response.log', 'a');
    fwrite($handle, '-- START -- (v.' . self::VERSION . ' ' . date('Y-m-d H:i:s') . ")n");
    fwrite($handle, ob_get_contents() . "n-- END --nnn");

Pay attention to that highlighted part and I’ll address it in a moment.

This code takes whatever is in the output buffer (which ultimately gets shown to the user) and chucks it in a file. Cool.

So how does it execute? I don’t call it explicitly. The __destruct is a special PHP function that gets automatically called when an instance of a class is about to get erased. It is rarely used by novice programmers because of its cryptic nature. But this is a good example where you might.

Since it triggers when the class instance gets destroyed, I just need to unset the variable that contains the instance. Near the bottom of my code I added:

unset($FRAMEWORK); // my class is a property inside this variable!

And, as expected, everything worked. Yes, second try! Wait, second??

This isn’t how the code looked when I tried it the first time. That highlighted portion, “CURRENT_FOLDER”, was missing. If I’m writing to the current folder, I shouldn’t have to specify a folder path… Usually. This failed, even though the same exact code in the constructor worked fine.

It turns out that when you try to do file-stuff during the destructor, PHP is no longer in the original folder you started out in. PHP has “forgotten” where your script is and has reverted to the root folder (AKA “/” or “C:”). This, in most systems, causes permission issues.

To get around this problem, you should be explicit about where you want to write the file. You can’t use relative paths (such as “…/logs/”). The “CURRENT_FOLDER” in my example happens to have the following value:

dirname($_SERVER['SCRIPT_FILENAME']) . '/'

The great part about this is that it is not relative. It will be the fully qualified path to the folder the script was run from.

Note: from the command line, you should always type in the full path to the script. Failure to do so will render PHP unable to figure out an absolute path to your script. Just a tip for you people writing cron scripts. 😉

I hope that helps!

2 thoughts on “Permission Denied in the PHP Destructor and the Current Folder

  1. You sir, are my hero for today 😉 I thought it was generally impossible to do a file write during implicit destruction. I never would have guessed php just changes path.

Comments are closed.