Back Again

Problem: For some reason, even though your PHP include_path does contain the location of your include file, PHP cannot seem to actually include() the file. The paths match exactly, and yet you still get errors.

Back on the air. I’ve been in the process of switching from my old QuickSilver G4 desktop to the new PowerBook, and when I took the old computer offline, I locked myself out of this blog. I actually run the editing client on my personal computer, but have a read-only version on the FreeBSD server that actually makes it public. So, when I took down the old computer, the site was still online, but not editable.

Getting the editing client running again was a fair amount of trouble. First there were all the code files to move over and into the right place. Then there was configuring Apache and PHP correctly. Then I needed to allow access to the database server from the new machine.

And then I got stuck. On the same problem that stuck me three years ago when I moved onto the QuickSilver: I could not include() in the code files for the blog. Or any files, for that matter.

Finally tracked down the problem, a teensy little thing, that I’m sure I’ll forget again by the time another three years goes by, and it’s time for the next new computer.

So, in the hopes that Google will find the answer when I try looking for it again:

Problem: For some reason, even though your PHP include_path does contain the location of your include file, PHP cannot seem to actually include() the file. The paths match exactly, and yet you still get errors.

Symptom: Trying to include() PHP code files into a main file results in errors like this:

Warning: main(include-file.inc): failed to open stream: No such file or directory in /path/to/main/file on line 18
Warning: main(): Failed opening ‘include-file.inc’ for inclusion (include_path=’.:/Users/username/Library/WebServer/…:/Library/WebServer/…’) in /Users/username/Sites/blog on line 18

Answer: You are keeping the include files in a location inside your own home directory (~/Library/... here). The permissons on ~/Library are no access for group and world. So the web server process cannot access them — even though the actual include directory has correct permissions.

Resolution: chmod go+rx ~/Library

Mac OS X ~/Library Permissions

Note to future self: the next time you re-install Mac OS X from scratch, remember that the reason why PHP cannot access include files in your ~/Library/WebServer folder is because the permissions on the ~/Library directory forbid read access to all but owner.

Before I explain the problem and solution that had me tearing my hair out Friday through Sunday, let me explain how I organize my system for doing PHP development and serving. Mac OS X Jaguar includes robust web serving capabilities, in the form of Apache and PHP. Apache’s default services, the documents and CGIs which are installed with Jaguar, are located in subdirectories under /Library/WebServer. This would be a natural place to put configuration and include files for PHP, and indeed it is where I keep the server-wide php.ini configuration file for PHP, /Library/WebServer/PHP/php.ini.

(I also create a symlink for that file at /usr/local/lib/php.ini, because that’s where Marc Liyanage’s full-featured PHP module, which I install over Apple’s “lite” version, expects to find its configuration file.)

However, Mac OS X separates out very cleanly the functionality installed at the system level, for all users, and functionality installed for a specific user. System level items go into /Library, while user-specific items go into ~/Library (that is, the Library folder in your home folder). The two directories mirror each other in structure, but have a different “scope” — system-wide versus user-specific. Since I was adding my blogging system’s PHP libraries for my own use only, I created the ~/Library/WebServer directory, and a PHP/Includes subdirectory under it, to hold them:

/Users/username/Library/WebServer/PHP/Includes/monauraljerk

I add the following line to my /private/etc/httpd/users/username.conf to make PHP look for include files in the above Includes folder:

path "/Users/username/Library/WebServer/PHP/Includes:/Library/WebServer/PHP/Includes"

This needs to go inside a VirtualHost or Directory statement; if you don’t know what those are, you might not want to be fiddling with this stuff.

The problem was, whenever I would load a PHP page that tried to include() one of the PHP libraries, or any file stored in my private Includes folder, it would fail with a “file not found” error. I spent more than 6 hours trying to track this problem down, finally resorting to brute force PHP scripts to test file_exists() on a bunch of different files, until I located the issue (and was able to blog once more!).

So, finally, here’s my point. Note to future self: the next time you re-install Mac OS X from scratch, remember that the reason why PHP cannot access include files in your ~/Library/WebServer folder is because the permissions on the ~/Library directory forbid read access to all but owner. You need to increase the permissions like this:

chmod go+r ~/Library

Remember it!