PHP’s include/require functions fails for paths with “../” or “./”

apache-2.2configurationPHP

I logged into my development server today to find that PHP was failing to include some files with this E_WARNING message:

Warning: include_once(../file2.php) [function.include-once]: failed to open stream: No such file or directory in /var/www/web/some_directory_1/file1.php on line whatever

I did some digging around with our sysadmin and we discovered that PHP only fails when it tries to include file paths with a '../' or './' in the path.

Suppose our file structure looks like this:

/var/www/web/
— index.php
— file2.php
— some_directory_1/
—- file1.php
—- file3.php

If file1.php wants to include file2.php, this will work:

include_once('/var/www/web/file2.php');

But this will not:

include_once('../file2.php');

Now, hold on a second… I know what you're thinking! "Oh, their include_path is just FUBAR." Well, not exactly.

If you do this in index.php, it works:

include_once('some_directory_1/file1.php');

And if you do this in file1.php, it also works:

include_once('file3.php');

Our include_path is set to .:/usr/lib/php. Nothing about the server environment been changed in the last 24 hours (no updates, no new software, no changes to the includes, no changes to the Apache or PHP configurations), myself and the sysadmin were the only people who accessed the server in the last 24 hours, and the includes were working just fine yesterday. We've exhausted our list of possible causes. Any clue what might cause this to happen?

Edit: Forgot the PHP warning message.

Best Answer

The reason you're having trouble is that the relative path in an include/require is always relative to the initial script, and using a relative path causes php to ignore the include_path value. So in your example include_once('../file2.php'); is looking for the file in the parent of index.php, assuming index.php is the initial script.

Not sure why it would suddenly change. But, the solution is to not use relative paths -- either use the include_path or use __DIR__/dirname() as suggested in the comments.

Related Topic