What's the problem?
I recently investigated the values of the PHP and Windows working directory for a variety of environments. My reason for doing so was that I could never quite understand how relative pathnames were resolved, and if you want to write code that will run, for example, both under Zend Studio, from the command line, and Apache, it matters. And it is not surprising that I never understood it either - every environment is different.
PHP working directory
The PHP working directory (from the PHP getcwd() function) will determine how PHP will interpret relative pathnames to PHP functions like PHP’s fopen(), file_get_contents() etc, as well as affect how files are found with include() and require().
Windows working directory
The Windows working directory (obtained with the Windows getcwd() call from direct.h) will determine how relative pathnames are resolved by Windows fopen() calls from within extensions.
Here are the results which illustrate that of the five different environments in which one of our PHP scripts might find itself running, not one of them is the same as any other. In conclusion, be warned: the chances of the Windows and the PHP working directories being the same is slim.
|Environment||PHP cwd (from PHP’s getcwd())||Windows cwd (from windows getcwd() in direct.h)|
|Zend Studio running internal debugger||location of the script||C:\Program Files\Zend\ZendStudioClient-5.1.0\bin\php5|
|Zend Studio running server debugger||C:\Program Files\Apache Group\Apache2\htdocs||C:\Program Files\Apache Group\Apache2|
|php-cli||same as the Windows cwd||normal command line working directory|
|php-cgi||location of the script||normal command line working directory|
|Apache||location of the script||C:\Program Files\Apache Group\Apache2|
What does it mean for me
The upshot of this is that you had better be careful which world you are in when you try to do things with files. Here’s something you can usually not do, which you might think you could: use the C library fopen() within an C or C++ extension on a pathname that you were given by PHP. Your PHP script may be able to open the file with PHP’s fopen() but that will be relative to PHP’s working directory and not Windows’. As you see from the table above these are rarely the same.
One thing that was throwing me for a long time is that we were passing PHP-working-directory-based relative pathnames into our SDO extension, which was then passing them on to libxml2 which was happily able to open them. It took a while for it to dawn on me (although I had come across it before) that the PHP libxml extension makes a call to libxml2 when PHP starts, and registers its own file handlers, so that any files that libxml2 needs to work with are actually resolved by the libxml extension, against PHP’s working directory and not Windows’. Thus without realising, our extension was working with PHP-based pathnames. Consequently we could pass the filename to libxml2 and it would be fine, but we could not fopen() the file ourselves.
Perhaps everyone else in the world already knew this and I am just catching up :-)
Matthew Peters[Read More]