Mark Clowes (38M 🇬🇧)

Index - Logical path function in PHP

2017-12-02
function logicalpath($path) {
    // same as realpath() except keeps logical paths
    if (!file_exists($path)) {
        return False;
    }
    $filename = '';
    if (is_file($path)) {
        $filename = (basename($path));
        $length = strlen($filename);
        $path = substr($path, 0, -$length);
        $filename = '/'.$filename;
    }
    return exec('bash -c "cd '. escapeshellarg($path) .' && pwd -L"').$filename;
}

I recently needed to be able to resolve the real logical path, similar to realpath() but leaving symlinks intact. I couldn't find an elegant way to do this without shelling out unfortunately. As far as I am aware it is functionally equivalent to realpath().

mac@localhost:~$ mkdir foo
mac@localhost:~$ mkdir bar
mac@localhost:~$ ln -s ../bar foo/
mac@localhost:~$ touch ~/foo/bar/xyzzy.txt
mac@localhost:~$ cd foo/bar
mac@localhost:~/foo/bar$ pwd -L
/home/mac/foo/bar
mac@localhost:~/foo/bar$ pwd -P
/home/mac/bar
mac@localhost:~/foo/bar$ php -a
Interactive mode enabled

php > include '/home/mac/paths.php';
php > echo(realpath('/home/mac/foo/bar/'));
/home/mac/bar
php > echo(logicalpath('/home/mac/foo/bar/'));
/home/mac/foo/bar
php > echo(logicalpath('/var/tmp/../../home/mac/foo/bar/'));
/home/mac/foo/bar
php > echo(logicalpath('/var/tmp/../../home/mac/foo/bar/xyzzy.txt'));
/home/mac/foo/bar/xyzzy.txt

GitHub Gist