Get Absolute Directory Path of Current File in PHP
If your code is including other files, you will encounter problems like «The file is not found». This is because, PHP doesn’t know the absolute path of file. So, if you are including files on another file, you should mention the absolute path of file.
But, If you’re PHP application is being used by other people, then the absolute path which you mentioned in your system won’t be the one of the others’ systems. So, you have to dynamically mention the absolute path that will work on any systems.
Example of Problem
Here is one of the case scenarios where you encounter the include problem.
Suppose, the index.php file is including the file1.php which is in the inc directory :
The inc directory also contains other files such as file2.php, file3.php, file4.php etc……. If you want to include the file2.php in file1.php like below, it won’t work :
In file1.php, the root directory is that of index.php. Because we are including the file1.php from index.php which is outside the directory.**
I think you understand the problem. Luckily, I have a solution that fixes this problem.
Solution of Problem
Since PHP 4.0.2, __FILE__ returns the absolute path of the running script even if it’s an include file. By giving the __FILE__ constant to the dirname function, you will get the directory of the script. So, code in file1.php would become :
The version 5.3.0 and it’s later versions have a new constant called __DIR__ which is the short way of dirname(__FILE__). You can also use this in replacement of what we used earlier. Now code in file1.php will become :
You can see more PHP Magic Constants in this manual page.
pathinfo
pathinfo() returns information about path : either an associative array or a string, depending on flags .
Note:
For information on retrieving the current path info, read the section on predefined reserved variables.
Note:
pathinfo() operates naively on the input string, and is not aware of the actual filesystem, or path components such as » .. «.
Note:
On Windows systems only, the \ character will be interpreted as a directory separator. On other systems it will be treated like any other character.
pathinfo() is locale aware, so for it to parse a path containing multibyte characters correctly, the matching locale must be set using the setlocale() function.
Parameters
If present, specifies a specific element to be returned; one of PATHINFO_DIRNAME , PATHINFO_BASENAME , PATHINFO_EXTENSION or PATHINFO_FILENAME .
If flags is not specified, returns all available elements.
Return Values
If the flags parameter is not passed, an associative array containing the following elements is returned: dirname , basename , extension (if any), and filename .
Note:
If the path has more than one extension, PATHINFO_EXTENSION returns only the last one and PATHINFO_FILENAME only strips the last one. (see first example below).
Note:
If the path does not have an extension, no extension element will be returned (see second example below).
Note:
If the basename of the path starts with a dot, the following characters are interpreted as extension , and the filename is empty (see third example below).
If flags is present, returns a string containing the requested element.
Examples
Example #1 pathinfo() Example
$path_parts = pathinfo ( ‘/www/htdocs/inc/lib.inc.php’ );
?php
echo $path_parts [ ‘dirname’ ], «\n» ;
echo $path_parts [ ‘basename’ ], «\n» ;
echo $path_parts [ ‘extension’ ], «\n» ;
echo $path_parts [ ‘filename’ ], «\n» ;
?>
The above example will output:
/www/htdocs/inc lib.inc.php php lib.inc
Example #2 pathinfo() example showing difference between null and no extension
$path_parts = pathinfo ( ‘/path/emptyextension.’ );
var_dump ( $path_parts [ ‘extension’ ]);
?php
$path_parts = pathinfo ( ‘/path/noextension’ );
var_dump ( $path_parts [ ‘extension’ ]);
?>
The above example will output something similar to:
string(0) "" Notice: Undefined index: extension in test.php on line 6 NULL
Example #3 pathinfo() example for a dot-file
The above example will output something similar to:
Array ( [dirname] => /some/path [basename] => .test [extension] => test [filename] => )
Example #4 pathinfo() example with array dereferencing
The flags parameter is not a bitmask. Only a single value may be provided. To select only a limited set of parsed values, use array destructuring like so:
[ ‘basename’ => $basename , ‘dirname’ => $dirname ] = pathinfo ( ‘/www/htdocs/inc/lib.inc.php’ );?php
var_dump ( $basename , $dirname );
?>
The above example will output something similar to:
string(11) "lib.inc.php" string(15) "/www/htdocs/inc"
See Also
- dirname() — Returns a parent directory’s path
- basename() — Returns trailing name component of path
- parse_url() — Parse a URL and return its components
- realpath() — Returns canonicalized absolute pathname
realpath
realpath() expands all symbolic links and resolves references to /./ , /../ and extra / characters in the input path and returns the canonicalized absolute pathname.
Parameters
Note:
Whilst a path must be supplied, the value can be an empty string. In this case, the value is interpreted as the current directory.
Return Values
Returns the canonicalized absolute pathname on success. The resulting path will have no symbolic link, /./ or /../ components. Trailing delimiters, such as \ and / , are also removed.
realpath() returns false on failure, e.g. if the file does not exist.
Note:
The running script must have executable permissions on all directories in the hierarchy, otherwise realpath() will return false .
Note:
For case-insensitive filesystems realpath() may or may not normalize the character case.
Note:
The function realpath() will not work for a file which is inside a Phar as such path would be a virtual path, not a real one.
Note:
On Windows, junctions and symbolic links to directories are only expanded by one level.
Note: Because PHP’s integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.
Examples
Example #1 realpath() example
chdir ( ‘/var/www/’ );
echo realpath ( ‘./../../etc/passwd’ ) . PHP_EOL ;
?php
echo realpath ( ‘/tmp/’ ) . PHP_EOL ;
?>
The above example will output:
Example #2 realpath() on Windows
On windows realpath() will change unix style paths to windows style.
echo realpath ( ‘/windows/system32’ ), PHP_EOL ;
?php
echo realpath ( ‘C:\Program Files\\’ ), PHP_EOL ;
?>
The above example will output:
C:\WINDOWS\System32 C:\Program Files
See Also
- basename() — Returns trailing name component of path
- dirname() — Returns a parent directory’s path
- pathinfo() — Returns information about a file path
User Contributed Notes 17 notes
Because realpath() does not work on files that do not
exist, I wrote a function that does.
It replaces (consecutive) occurences of / and \\ with
whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine.
Paths returned by get_absolute_path() contain no
(back)slash at position 0 (beginning of the string) or
position -1 (ending)
function get_absolute_path ( $path ) $path = str_replace (array( ‘/’ , ‘\\’ ), DIRECTORY_SEPARATOR , $path );
$parts = array_filter ( explode ( DIRECTORY_SEPARATOR , $path ), ‘strlen’ );
$absolutes = array();
foreach ( $parts as $part ) if ( ‘.’ == $part ) continue;
if ( ‘..’ == $part ) array_pop ( $absolutes );
> else $absolutes [] = $part ;
>
>
return implode ( DIRECTORY_SEPARATOR , $absolutes );
>
?>
A test:
var_dump ( get_absolute_path ( ‘this/is/../a/./test/.///is’ ));
?>
Returns: string(14) «this/a/test/is»
As you can so, it also produces Yoda-speak. 🙂
namespace MockingMagician \ Organic \ Helper ;
class Path
/**
* There is a method that deal with Sven Arduwie proposal https://www.php.net/manual/en/function.realpath.php#84012
* And runeimp at gmail dot com proposal https://www.php.net/manual/en/function.realpath.php#112367
* @param string $path
* @return string
*/
public static function getAbsolute ( string $path ): string
// Cleaning path regarding OS
$path = mb_ereg_replace ( ‘\\\\|/’ , DIRECTORY_SEPARATOR , $path , ‘msr’ );
// Check if path start with a separator (UNIX)
$startWithSeparator = $path [ 0 ] === DIRECTORY_SEPARATOR ;
// Check if start with drive letter
preg_match ( ‘/^[a-z]:/’ , $path , $matches );
$startWithLetterDir = isset( $matches [ 0 ]) ? $matches [ 0 ] : false ;
// Get and filter empty sub paths
$subPaths = array_filter ( explode ( DIRECTORY_SEPARATOR , $path ), ‘mb_strlen’ );
$absolutes = [];
foreach ( $subPaths as $subPath ) if ( ‘.’ === $subPath ) continue;
>
// if $startWithSeparator is false
// and $startWithLetterDir
// and (absolutes is empty or all previous values are ..)
// save absolute cause that’s a relative and we can’t deal with that and just forget that we want go up
if ( ‘..’ === $subPath
&& ! $startWithSeparator
&& ! $startWithLetterDir
&& empty( array_filter ( $absolutes , function ( $value ) < return !( '..' === $value ); >))
) $absolutes [] = $subPath ;
continue;
>
if ( ‘..’ === $subPath ) array_pop ( $absolutes );
continue;
>
$absolutes [] = $subPath ;
>
return
(( $startWithSeparator ? DIRECTORY_SEPARATOR : $startWithLetterDir ) ?
$startWithLetterDir . DIRECTORY_SEPARATOR : »
). implode ( DIRECTORY_SEPARATOR , $absolutes );
>
/**
* Examples
*
* echo Path::getAbsolute(‘/one/two/../two/./three/../../two’); => /one/two
* echo Path::getAbsolute(‘../one/two/../two/./three/../../two’); => ../one/two
* echo Path::getAbsolute(‘../.././../one/two/../two/./three/../../two’); => ../../../one/two
* echo Path::getAbsolute(‘../././../one/two/../two/./three/../../two’); => ../../one/two
* echo Path::getAbsolute(‘/../one/two/../two/./three/../../two’); => /one/two
* echo Path::getAbsolute(‘/../../one/two/../two/./three/../../two’); => /one/two
* echo Path::getAbsolute(‘c:\.\..\one\two\..\two\.\three\..\..\two’); => c:/one/two
*
*/
>
Needed a method to normalize a virtual path that could handle .. references that go beyond the initial folder reference. So I created the following.
function normalizePath ( $path )
$parts = array(); // Array to build a new path from the good parts
$path = str_replace ( ‘\\’ , ‘/’ , $path ); // Replace backslashes with forwardslashes
$path = preg_replace ( ‘/\/+/’ , ‘/’ , $path ); // Combine multiple slashes into a single slash
$segments = explode ( ‘/’ , $path ); // Collect path segments
$test = » ; // Initialize testing variable
foreach( $segments as $segment )
if( $segment != ‘.’ )
$test = array_pop ( $parts );
if( is_null ( $test ))
$parts [] = $segment ;
else if( $segment == ‘..’ )
if( $test == ‘..’ )
$parts [] = $test ;
if( $test == ‘..’ || $test == » )
$parts [] = $segment ;
>
else
$parts [] = $test ;
$parts [] = $segment ;
>
>
>
return implode ( ‘/’ , $parts );
>
?>
Will convert /path/to/test/.././..//..///..///../one/two/../three/filename
to ../../one/three/filename
realpath() is just a system/library call to actual realpath() function supported by OS. It does not work on a path as a string, but also resolves symlinks. The resulting path might significantly differs from the input even when absolute path is given. No function in this notes resolves that.
The suggestion on the realpath man page is to look for an existing parent directory. Here is an example:
function resolvePath ( $path ) if( DIRECTORY_SEPARATOR !== ‘/’ ) $path = str_replace ( DIRECTORY_SEPARATOR , ‘/’ , $path );
>
$search = explode ( ‘/’ , $path );
$search = array_filter ( $search , function( $part ) return $part !== ‘.’ ;
>);
$append = array();
$match = false ;
while( count ( $search ) > 0 ) $match = realpath ( implode ( ‘/’ , $search ));
if( $match !== false ) break;
>
array_unshift ( $append , array_pop ( $search ));
>;
if( $match === false ) $match = getcwd ();
>
if( count ( $append ) > 0 ) $match .= DIRECTORY_SEPARATOR . implode ( DIRECTORY_SEPARATOR , $append );
>
return $match ;
>
?>
The result will retrieve absolute path for non-existing relative path. Even if a path does not exists, there should be existing directory somewhere, for which the realpath could be obtained. If this is not within the relative path (i.e. even current working directory does not exists), getcwd() will retrieve absolute path, so some absolute path is returned (although in that case the PHP process could have huge problems).
Note: If you use this to check if a file exists, it’s path will be cached, and returns true even if the file is removed (use file_exists instead).