I know this has been answered and accepted but I didn't see anyone chiming in on why this solution worked and what was incorrect in the first place.
The short description of the problem
The current working directory is established at the point php get's it's hands on the request and all relative paths are resolved based on the current working directory, not the directory of the file that the path is referenced in.
The long description of the problem
Relative paths in php are resolved based on the current working directory.
For testing purposes you can always see what the current working directory is by calling getcwd
This value is initially arrived at on an http request as the directory that contains the file that the web server initially handed off the request to php.
So for example if you go to http://www.mydomain.com/index.php the current working directory will be the same as the document root ($_SERVER["DOCUMENT_ROOT"]
)
For a CLI request the cwd is the directory you are in when you execute the command. So if I am at /home/orangepill
and I run /usr/bin/php /path/to/file.php
the cwd will be /home/orangepill
.
This causes a problem for relative file references within included files.
Lets take this example.
Client navigates to www.mydomain.com
Apache has index.php set in the DirectoryIndex directive and apache finds an index.php file in the document root. Current working directory is set to the document root.
/index.php contains the line include "library/myclass.php";
$_SERVER["DOCUMENT_ROOT"]."/library/myclass.php" exists and all is good
myclass.php contains the line include("myclass_helper.php");
this resolves to $_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php". (remember relative references resolve relative to the current working directory)
$_SERVER["DOCUMENT_ROOT"]."/myclass_helper.php"
doesn't exist its actually in $_SERVER["DOCUMENT_ROOT"]."/library/myclass_helper.php"
You are probably thing but wait... I've experienced different behavior in my scripts when including within an include. The reason for that is the include and require language constructs (along with a couple of other file system commands) try to include relative paths from each of the paths specified in the include path php directive. So in the above example if library directory off of the document root existed within the include paths then everything would work as expected.
A wholesale solution for requiring files relative to the current file is to structure your include paths using the __DIR__
contextual constant. So you would use include __DIR__."/myclass_helper.php";
(include dirname(__FILE__)."/myclass_helper.php
in pre PHP 5.3 environments) and at runtime this would effectively convert your relative path to an absolute path based on the location of the file doing the include.
For common include directories I have gotten into the habit of specifying a few commonly used locations for use with relative file system references. for example
define ("APPLICATION_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/application");
define ("LIBRARY_PATH", realpath($_SERVER["DOCUMENT_ROOT"]."/library");
define ("CONFIG_PATH", APPLICATION_PATH."/etc/";
This gives you a lot of anchor points to include paths relative to.