This follows on from my article from an hour or so ago "PHP: include paths are relative to the current working directory". The situation there was daft but at least had a precedent in other languages.
But this? This beggar's belief.
Over and above the weirdo behaviour I saw in the previous article, I had been seeing other behaviour which just didn't add up. And I could not work out WTF was going on, until just now.
For this experiment, I have these files:
include/
working/
actual/
callMe2.php
incExistsInActualAndWorking.php
incExistsOnlyInActual
incExistsInActualAndWorking.php
And the files are:
<?php
// callMe2.php
printf("Working directory: %s\n\n\n", getcwd());
echo "including incExistsOnlyInActual.php\n";
include "incExistsOnlyInActual.php";
echo "\n\n";
echo "including ./incExistsOnlyInActual.php\n";
include "./incExistsOnlyInActual.php";
echo "\n\n================================\n\n";
echo "including incExistsInActualAndWorking.php\n";
include "incExistsInActualAndWorking.php";
echo "\n\n";
echo "including ./incExistsInActualAndWorking.php\n";
include "./incExistsInActualAndWorking.php";
<?php
// incExistsOnlyInActual.php
echo "included actual/incExistsOnlyInActual.php\n\n";
<?php
// actual/incExistsInActualAndWorking.php
echo "included actual/incExistsInActualAndWorking.php\n\n";
<?php
// working/incExistsInActualAndWorking.php
echo "included working/incExistsInActualAndWorking.php\n\n";
When I run
callMe2.php
from the working directory, I get this:
C:\include\working>php actual\callMe2.php
Working directory: C:\include\working
including incExistsOnlyInActual.php
included actual/incExistsOnlyInActual.php
including ./incExistsOnlyInActual.php
PHP Warning: include(./incExistsOnlyInActual.php): failed to open stream: No such file or directory in C:\include\working\actual\callMe2.php on line 9
Warning: include(./incExistsOnlyInActual.php): failed to open stream: No such file or directory in C:\include\working\actual\callMe2.php on line 9
PHP Warning: include(): Failed opening './incExistsOnlyInActual.php' for inclusion (include_path='.;C:\php\pear') in C:\include\working\actual\callMe2.php on line 9
Warning: include(): Failed opening './incExistsOnlyInActual.php' for inclusion (include_path='.;C:\php\pear') in C:\include\working\actual\callMe2.php on line 9
================================
including incExistsInActualAndWorking.php
included working/incExistsInActualAndWorking.php
including ./incExistsInActualAndWorking.php
included working/incExistsInActualAndWorking.php
C:\include\working>
Working directory: C:\include\working
including incExistsOnlyInActual.php
included actual/incExistsOnlyInActual.php
including ./incExistsOnlyInActual.php
PHP Warning: include(./incExistsOnlyInActual.php): failed to open stream: No such file or directory in C:\include\working\actual\callMe2.php on line 9
Warning: include(./incExistsOnlyInActual.php): failed to open stream: No such file or directory in C:\include\working\actual\callMe2.php on line 9
PHP Warning: include(): Failed opening './incExistsOnlyInActual.php' for inclusion (include_path='.;C:\php\pear') in C:\include\working\actual\callMe2.php on line 9
Warning: include(): Failed opening './incExistsOnlyInActual.php' for inclusion (include_path='.;C:\php\pear') in C:\include\working\actual\callMe2.php on line 9
================================
including incExistsInActualAndWorking.php
included working/incExistsInActualAndWorking.php
including ./incExistsInActualAndWorking.php
included working/incExistsInActualAndWorking.php
C:\include\working>
What?
A reminder:
./incExistsOnlyInActual.php
and incExistsOnlyInActual.php
are relative references to exactly the same file "." just means "the current dir". So one is an explicit reference to the current dir, the other is implicit. The canonical path for both of these references is the same.Yet... PHP handles them differently. Without the ./, PHP seems to do this:
- looks in the working directory;
- if the file is not there, looks in the directory the file making the include call is in.
It would make more sense if those two look-ups were reversed, but there's some logic there.
However if the file reference does have the "
./
", then PHP only looks in the working directory (not the current directory, I hasten to add).I can understand one of these behaviours or the other. But not two different bloody behaviours for two different ways of referencing a relative path. That's just fuckin' stupid.
What on earth are you thinking, PHP? It's either just white noise, or elevator music1, I think.
Grrrr.
--
Adam
1 I am actually finding myself thinking of this clip from Dawn of the Dead when I write that.