include dirname(__FILE__).'/../../index.php';
is your best bet here, and it will avoid most of the relative path bugs you can encounter with other solutions.
Indeed, it will force the include to always be relative to the position of the current script where this code is placed (which location is most likely stable, since you define the architecture of your application). This is different from just doing include '../../index.php'
which will include relatively to the executing (also named "calling") script and then relatively to the current working directory, which will point to the parent script that includes your script, instead of resolving from your included script's path.
From the PHP documentation:
Files are included based on the file path given or, if none is given,
the include_path specified. If the file isn't found in the
include_path, include will finally check in the calling script's own
directory and the current working directory before failing.
And the oldest post I've found citing this trick dates back to 2003, by Tapken.
You can test with the following setup:
Create a layout like this:
htdocs
¦ parent.php
¦ goal.php
¦
+---sub
¦ included.php
¦ goal.php
In parent.php
, put:
<?php
include dirname(__FILE__).'/sub/included.php';
?>
In sub/included.php
, put:
<?php
print("WRONG : " . realpath('goal.php'));
print("GOOD : " . realpath(dirname(__FILE__).'/goal.php'));
?>
Result when accessing parent.php
:
WRONG : X:\htdocs\goal.php
GOOD : X:\htdocs\sub\goal.php
As we can see, in the first case, the path is resolved from the calling script parent.php
, while by using the dirname(__FILE__).'/path'
trick, the include is done from the script included.php
where the code is placed in.
Beware, the following NOT equivalent to the trick above contrary to what can be read elsewhere:
include '/../../index.php';
Indeed, prepending /
will work, but it will resolve just like include ../../index.php
from the calling script (the difference is that include_path
won't be looked afterwards if it fails). From PHP doc:
If a path is defined — whether absolute (starting with a drive letter
or \ on Windows, or / on Unix/Linux systems) or relative to the
current directory (starting with . or ..) — the include_path will be
ignored altogether.