127

How do you include a file that is more than 2 directories back. I know you can use ../index.php to include a file that is 2 directories back, but how do you do it for 3 directories back? Does this make sense? I tried .../index.php but it isn't working.

I have a file in /game/forum/files/index.php and it uses PHP include to include a file. Which is located in /includes/boot.inc.php; / being the root directory.

hakre
  • 193,403
  • 52
  • 435
  • 836

19 Answers19

193

.. selects the parent directory from the current. Of course, this can be chained:

../../index.php

This would be two directories up.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • 1
    @Brian Well, that’s nonsense, you’re comparing apples and oranges. You’re right that a `define` would be used here but (1) that wasn’t even remotely the question here. And (2) you’d still use a relative path in your `define`, Unless you actually hard-code the whole absolute server path and I would refrain from that since it has only disadvantages. Or (the third alternative) you could use string manipulation to extract parent directory from the (expanded) current path but once again this doesn’t have *any* advantages to using relative paths. – Konrad Rudolph Aug 20 '12 at 09:24
  • Sadly this may work on one device and not another, `/../` may work or `../` may work, or neither may work on three different computers with the exact same environment setup – Douglas Gaskell Oct 04 '17 at 17:23
  • @DouglasGaskell No, that’s incorrect. The relative path notation, including `../` and `../../` (note: **no** leading slash!), works on all modern operating systems. It *used to* not work on Windows and (*long* ago) Macintosh but it now works everywhere, and has for at least the last ten years. If it doesn’t work somewhere then the reason is that the file structure is different, and/or you’re in a different working directory. But it’s unrelated to this code. – Konrad Rudolph Oct 04 '17 at 17:31
  • Konrad, I mention this since I just dealt with this issue not 10 minutes ago after sharing a repository with a coworker, using a VM snapshot. For some reason all the paths had to have `/../` instead of `../` on his environment. – Douglas Gaskell Oct 04 '17 at 18:07
  • @DouglasGaskell And I can tell you with confidence that the error is unrelated. In fact, the path `/../` simply makes no sense on any system (it's equivalent to `/`, or an error). Are you sure you're not *pasting* something in front of it? – Konrad Rudolph Oct 04 '17 at 18:59
55

To include a file one directory back, use '../file'. For two directories back, use '../../file'. And so on.

Although, realistically you shouldn't be performing includes relative to the current directory. What if you wanted to move that file? All of the links would break. A way to ensure that you can still link to other files, while retaining those links if you move your file, is:

require_once($_SERVER['DOCUMENT_ROOT'] . 'directory/directory/file');

DOCUMENT_ROOT is a server variable that represents the base directory that your code is located within.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
Dan Hulton
  • 1,793
  • 11
  • 15
  • 2
    Hey Dan quick question: you say "***realistically you shouldn't be performing includes relative to the current directory***". What about all the relative paths that are littered throughout most HTML documents? If I moved my file, wouldn't those break as well? Is there a standard of when to use relative vs absolute links? Thank you in advance! – Govind Rai Nov 10 '16 at 01:21
  • 2
    i think its missing one slash , it should be : require_once($_SERVER['DOCUMENT_ROOT'] . '/directory/directory/file'); – user889030 Dec 06 '17 at 18:46
  • @user889030 as far as I know, that slash is not needed, at least in most of the cases – BotMaster3000 Jan 18 '18 at 12:36
  • 1
    @BotMaster3000 hmmm : http://sandbox.onlinephpfunctions.com/code/66851aa1a964ae81d727c235fe416a3745b5e037 – user889030 Jan 24 '18 at 04:54
31
. = current directory
.. = parent directory

So ../ gets you one directory back not two.

Chain ../ as many times as necessary to go up 2 or more levels.

Joe Skora
  • 14,735
  • 5
  • 36
  • 39
24
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.

gaborous
  • 15,832
  • 10
  • 83
  • 102
  • @diEcho: may I know why it "is completely wrong"? I am using it on several professional-grades application and this method is actually the only one that worked in every situation. It's also detailed in the [php manual](http://php.net/manual/en/function.include.php): it can't be that wrong. – gaborous Oct 25 '12 at 22:50
  • first line is completely wrong. You can not add `..` middle of the path (relative/absolute). – xkeshav Oct 26 '12 at 04:17
  • @diEcho I should also point you to the PHP manual: http://php.net/manual/en/function.include.php – gaborous Oct 26 '12 at 22:03
  • tell me a single example, where `..` is used middle of the include. it always should be the first part of include – xkeshav Oct 29 '12 at 04:21
  • https://github.com/lrq3000/dolibarr_customfields/blob/3.2/htdocs/customfields/core/substitutions/functions_customfields.lib.php#L56 A professional-grade module for a professional-grade ERP/CRM. You, sir, should not talk when you shan't know what you say. – gaborous Oct 29 '12 at 16:18
  • @diEcho: also you should know that every include is automatically resolved since PHP 4.peanuts, in a way similar to what realpath() does. – gaborous Oct 29 '12 at 16:22
  • at first I too thought @gaborous is wrong, but I tried! :-) It works! And, as i think, this should be the accepted answer, since this will help a lot in working local and live without hassle :-) thanks gaborous – Arun Shankar Jan 29 '16 at 17:47
  • @DevTest You're welcome, and please excuse me for some of my somewhat angry comments above. – gaborous Jan 30 '16 at 13:49
16

../ is one directory, Repeat for two directories ../../ or even three: ../../../ and so on.

Defining constants may reduce confusion because you will drill forward into directories verses backwards

You could define some constants like so:

define('BD', '/home/user/public_html/example/');

define('HTMLBD', 'http://example.com/');

When using 'BD' or my 'base directory' it looks like so:

file(BD.'location/of/file.php');

define(); reference

Brian Dillingham
  • 9,118
  • 3
  • 28
  • 47
16
../../index.php 

       

dippas
  • 58,591
  • 15
  • 114
  • 126
bdukes
  • 152,002
  • 23
  • 148
  • 175
12
../../../includes/boot.inc.php

Each instance of ../ means up/back one directory.

leek
  • 11,803
  • 8
  • 45
  • 61
12

Try This

this example is one directory back

require_once('../images/yourimg.png');

this example is two directory back

require_once('../../images/yourimg.png');
rajpoot rehan
  • 435
  • 5
  • 14
10

if you are using php7 you can use dirname function with level parameter of 2, for example :

dirname("/usr/local/lib", 2);

the second parameter "2" indicate how many level up

dirname referance

ron
  • 726
  • 11
  • 16
9

following are ways to access your different directories:-

./ = Your current directory
../ = One directory lower
../../ = Two directories lower
../../../ = Three directories lower
user2951753
  • 103
  • 1
  • 3
  • 13
8

I recomend to use __DIR__ to specify current php file directory. Check here for the reason.

__DIR__ . /../../index.php
Community
  • 1
  • 1
LF00
  • 27,015
  • 29
  • 156
  • 295
7

You can do ../../directory/file.txt - This goes two directories back.

../../../ - this goes three. etc

dippas
  • 58,591
  • 15
  • 114
  • 126
Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
7
../../../index.php

         

dippas
  • 58,591
  • 15
  • 114
  • 126
MazarD
  • 2,759
  • 2
  • 22
  • 33
7

But be VERY careful about letting a user select the file. You don't really want to allow them to get a file called, for example,

../../../../../../../../../../etc/passwd

or other sensitive system files.

(Sorry, it's been a while since I was a linux sysadmin, and I think this is a sensitive file, from what I remember)

ZombieSheep
  • 29,603
  • 12
  • 67
  • 114
5
../../../includes/boot.inc.php
dippas
  • 58,591
  • 15
  • 114
  • 126
HAXEN
  • 388
  • 1
  • 2
  • 13
3

including over directories can be processed by proxy file

  • root
  • .....|__web
  • .....|.........|_requiredDbSettings.php
  • .....|
  • .....|___db
  • .....|.........|_dbsettings.php
  • .....|
  • .....|_proxy.php

    dbsettings.php:
    $host='localhost';
    $user='username':
    $pass='pass';
    
    proxy.php:
    include_once 'db/dbsettings.php
    
    requiredDbSettings.php:
    include_once './../proxy.php';
    
dippas
  • 58,591
  • 15
  • 114
  • 126
allenn
  • 31
  • 1
2

I saw your answers and I used include path with syntax

require_once '../file.php'; // server internal error 500

and http server (Apache 2.4.3) returned internal error 500.

When I changed the path to

require_once '/../file.php'; // OK

everything is fine.

Bronek
  • 10,722
  • 2
  • 45
  • 46
2

Try ../../. You can modify it accordingly as it will take you up back two directories. First reach to root directory then access the required directory.

E.g. You are in root/inc/usr/ap and there is another directory root/2nd/path. You can access the path directory from ap like this: ../../2nd/path first go to root than desired directory. If not working please share.

Hans Then
  • 10,935
  • 3
  • 32
  • 51
khan
  • 21
  • 1
2

if you include the / at the start of the include, the include will be taken as the path from the root of the site.

if your site is http://www.example.com/game/forum/files/index.php you can add an include to /includes/boot.inc.php which would resolve to http://www.example.com/includes/boot.inc.php .

You have to be careful with .. traversal as some web servers have it disabled; it also causes problems when you want to move your site to a new machine/host and the structure is a little different.

dippas
  • 58,591
  • 15
  • 114
  • 126
Mauro
  • 4,531
  • 3
  • 30
  • 56