Short version:
How do relative paths work in php?
Long version:
I have a local web site (http://test.com) and E:\test\ is its document root. This is my Directory tree:
- E:\test\001.php
- E:\test\exit.php
- E:\test\death.txt
- E:\test\mysql\first.php
- E:\test\mysql\death.txt
- E:\test\mysql\exit.php
And Contents of files:
E:\test\001.php
<?php
include('mysql/first.php');
?>
E:\test\exit.php
<?php
die('What?');
?>
E:\test\death.txt
Bonjour
E:\test\mysql\first.php
<?php
echo file_get_contents('death.txt');
include('exit.php');
?>
E:\test\mysql\death.txt
Hello there
E:\test\mysql\exit.php
<?php
die('DONE');
?>
If I browse http://test.com/001.php and E:\test\exit.php and E:\test\death.txt exist, I get this:
BonjourWhat?
And If they don’t exist:
Warning: file_get_contents(death.txt) [function.file-get-contents]: failed to open stream: No such file or directory in E:\test\mysql\first.php on line 2
DONE
How do relative paths workin php? I thought it should give me warning for both files or show proper output !
I’m testing this code on Win7 x64 with XAMPP, php 5.3.
This is how the documentation on php.net describes the PHP
includesearch mechanism:http://php.net/manual/en/ini.core.php#ini.include-path.
case, the root directory)
When I ran your scripts, my include path was set to
.:by default (the current directory and nothing else), so when I try to loaddeath.txtandexit.phpfrommysql/first.phpit should search in./folder which is the current directory. But… It does not. The current directory should bemysql/but it’s not pointing there… So what’s happening here?PHP is quite special with that… Let’s rollback to the first statement we made. What is PHP interpreting in our
include pathwhen it uses the.is actually a path resolution again! So, looking at our path, we have.which can’t be interpreted (./.again?) to anything using our include_path. Then, PHP has to go to the second path resolution (2) which is the root directory of our script. (have you got an headache yet? Because I do)Using
get_include_path()andrealpath()you can observe this:Then, why does it specifically fail to load
mysql/death.txtbut still findmysql/exit.php, once you removedeath.txtandexit.phpfrom your root directory? It should find both of them, right?Well, it’s because
get_file_contenthas a second parameter which ignoresinclude_pathby default.If you set the second parameter:
Then you would get the expected result.
The funny thing is that
get_file_content()will start using the same mechanism asinclude(and this is not documented properly on php.net). Andrealpath()doesn’t even implement this mechanism at all (which explains why I have ano path returnedshowing up).Hope this helps!