89

In PHP, what would be the cleanest way to get the parent directory of the current running script relative to the www root? Assume I have:

$_SERVER['SCRIPT_NAME'] == '/relative/path/to/script/index.php'

Or just:

$something_else == '/relative/path/to/script/'

And I need to get /relative/path/to/ with slashes properly inserted. What would you suggest? A one liner is preferred.

EDIT

I need to get a path relative to the www root, dirname(__FILE__) gives me an absolute path in the filesystem so that won't work. $_SERVER['SCRIPT_NAME'] on the other hand 'starts' at the www root.

Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185

13 Answers13

173

If your script is located in /var/www/dir/index.php then the following would return:

dirname(__FILE__); // /var/www/dir

or

dirname( dirname(__FILE__) ); // /var/www

Edit

This is a technique used in many frameworks to determine relative paths from the app_root.

File structure:

 /var/
      www/
          index.php
          subdir/
                 library.php

index.php is my dispatcher/boostrap file that all requests are routed to:

define(ROOT_PATH, dirname(__FILE__) ); // /var/www

library.php is some file located an extra directory down and I need to determine the path relative to the app root (/var/www/).

$path_current = dirname( __FILE__ ); // /var/www/subdir
$path_relative = str_replace(ROOT_PATH, '', $path_current); // /subdir

There's probably a better way to calculate the relative path then str_replace() but you get the idea.

Mike B
  • 31,886
  • 13
  • 87
  • 111
  • That won't work as I need the path relative to the www root. I could just replace the /var/www part out of it, but this needs to work on Windows and *nix. – Tatu Ulmanen Dec 10 '09 at 16:22
  • There is no dependable sure-fire way of determining the ROOT_PATH on all OS's on all servers. The best practice technique is to `define(ROOT_PATH, dirname(__FILE__));` early in your stack (hopefully you use a common dispatcher or bootstrap so this won't be a headache to implement) and use that in conjunction with other functions to produce a relative path. – Mike B Dec 10 '09 at 16:37
  • In my case it's the other way down. All requests are routed to /something/cms/index.php so setting ROOT_PATH from there results in /something/cms/, and I need to access the parent directory /something/. So I guess I'll just have to resort to some ugly string manipulation. – Tatu Ulmanen Dec 10 '09 at 17:54
  • I've been using `$_SERVER['SCRIPT_NAME']` to get the directory, but I like this idea. Excellent answer. – Amal Murali Nov 20 '13 at 19:41
  • 3
    As of PHP 7.0.0, `dirname(__FILE__, 2)` can be used instead of `dirname(dirname(__FILE__))`. [`dirname` Changelog](https://www.php.net/manual/en/function.dirname.php#refsect1-function.dirname-changelog) – Leon Williams Oct 10 '20 at 22:31
15

As of PHP 5.3.0 you can use __DIR__ for this purpose.

The directory of the file. If used inside an include, the directory of the included file is returned. This is equivalent to dirname(__ FILE__).

See PHP Magic constants.

C:\www>php --version
PHP 5.5.6 (cli) (built: Nov 12 2013 11:33:44)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies

C:\www>php -r "echo __DIR__;"
C:\www
12

To get the parentdir of the current script.

$parent_dir = dirname(__DIR__);
hans
  • 121
  • 1
  • 3
8

If I properly understood your question, supposing your running script is

/relative/path/to/script/index.php

This would give you the parent directory of your running script relative to the document www:

$parent_dir = dirname(dirname($_SERVER['SCRIPT_NAME'])) . '/';
//$parent_dir will be '/relative/path/to/'

If you want the parent directory of your running script relative to server root:

$parent_dir = dirname(dirname($_SERVER['SCRIPT_FILENAME'])) . '/';
//$parent_dir will be '/root/some/path/relative/path/to/'
Marco Demaio
  • 33,578
  • 33
  • 128
  • 159
  • Hi! I've tried to ask this before... Is it common practice to put a trailing slash or omit it? I like to omit it because: `$url = BASE_URL . '/my/path/';` looks better to me than `$url = BASE_URL . 'my/path/';`. Is there a standard way or what's most common? – nkkollaw May 29 '13 at 21:43
  • @nbrogi: I like to always add it, so you can immediately see it's a directory/folder and not a file name without the extension. – Marco Demaio Jun 05 '13 at 17:11
6

I Hope this will help you.

echo getcwd().'<br>'; // getcwd() will return current working directory
echo dirname(getcwd(),1).'<br>';
echo dirname(getcwd(),2).'<br>';
echo dirname(getcwd(),3).'<br>';

Output :

C:\wamp64\www\public_html\step
C:\wamp64\www\public_html
C:\wamp64\www
C:\wamp64
Vignesh KM
  • 1,979
  • 1
  • 18
  • 24
5

Fugly, but this will do it:

substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'],basename($_SERVER['SCRIPT_NAME'])))
Sliq
  • 15,937
  • 27
  • 110
  • 143
Brad
  • 51
  • 1
  • 1
2

Here is what I use since I am not running > 5.2

function getCurrentOrParentDirectory($type='current')
{
    if ($type == 'current') {
        $path = dirname(__FILE__);  
    } else {
        $path = dirname(dirname(__FILE__));
    }
    $position = strrpos($path, '/') + 1;
    return substr($path, $position);
}

Double dirname with file as suggested by @mike b for the parent directory, and current directory is found by just using that syntax once.

Note this function only returns the NAME, slashes have to be added afterwards.

Alex
  • 9,215
  • 8
  • 39
  • 82
2
$dir = dirname($file) . DIRECTORY_SEPARATOR;
Jordan Ryan Moore
  • 6,877
  • 2
  • 26
  • 27
  • 1
    But isn't a `DIRECTORY_SEPARATOR define` a needless thing? PHP seems to work well with both type of slashes `/ \\` also on Windows machines. – Marco Demaio Nov 25 '12 at 10:45
2

This is a function that I use. Created it once so I always have this functionality:

function getDir(){
    $directory = dirname(__FILE__);
    $directory = explode("/",$directory);
    $findTarget = 0;
    $targetPath = "";
    foreach($directory as $dir){
        if($findTarget == 1){
            $targetPath = "".$targetPath."/".$dir."";
        }
        if($dir == "public_html"){
            $findTarget = 1;
        }
    }
    return "http://www.".$_SERVER['SERVER_NAME']."".$targetPath."";
}
John
  • 21
  • 1
  • If I understand well this script seeks the absolute path to "public_html". In this case, shouldn't the ' == ' symbol be replaced by ' != ' ? – gcousin Mar 31 '20 at 21:50
1

Try this. Works on both windows or linux server..

str_replace('\\','/',dirname(dirname(__FILE__)))

cestar
  • 19
  • 1
0

This is also a possible solution

$relative = '/relative/path/to/script/';
$absolute = __DIR__. '/../' .$relative;
0

I hope this will help

function get_directory(){
    $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
    $protocol = substr(strtolower($_SERVER["SERVER_PROTOCOL"]), 0, strpos(strtolower($_SERVER["SERVER_PROTOCOL"]), "/")) . $s;
    $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
return $protocol . "://" . $_SERVER['SERVER_NAME'] . dirname($_SERVER['PHP_SELF']);
}
define("ROOT_PATH", get_directory()."/" );
echo ROOT_PATH;
-7

Got it myself, it's a bit kludgy but it works:

substr(dirname($_SERVER['SCRIPT_NAME']), 0, strrpos(dirname($_SERVER['SCRIPT_NAME']), '/') + 1)

So if I have /path/to/folder/index.php, this results in /path/to/.

Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185
  • 2
    I don't understand you simply need to call twice `dirname` in order to reach the parent directory, see my answer. – Marco Demaio May 09 '11 at 19:20