Replace PHP's realpath()

前端 未结 6 1896
悲哀的现实
悲哀的现实 2020-12-05 01:21

Apparently, realpath is very buggy. In PHP 5.3.1, it causes random crashes. In 5.3.0 and less, realpath randomly fails and returns false (for the s

6条回答
  •  再見小時候
    2020-12-05 01:48

    I know this is an old thread, but it is really helpful.

    I meet a weird Phar::interceptFileFuncs issue when I implemented relative path in phpctags, the realpath() is really really buggy inside phar.

    Thanks this thread give me some lights, here comes with my implementation based on christian's implemenation from this thread and this comments.

    Hope it works for you.

    function relativePath($from, $to)
    {
        $fromPath = absolutePath($from);
        $toPath = absolutePath($to);
    
        $fromPathParts = explode(DIRECTORY_SEPARATOR, rtrim($fromPath, DIRECTORY_SEPARATOR));
        $toPathParts = explode(DIRECTORY_SEPARATOR, rtrim($toPath, DIRECTORY_SEPARATOR));
        while(count($fromPathParts) && count($toPathParts) && ($fromPathParts[0] == $toPathParts[0]))
        {
            array_shift($fromPathParts);
            array_shift($toPathParts);
        }
        return str_pad("", count($fromPathParts)*3, '..'.DIRECTORY_SEPARATOR).implode(DIRECTORY_SEPARATOR, $toPathParts);
    }
    
    function absolutePath($path)
    {
        $isEmptyPath    = (strlen($path) == 0);
        $isRelativePath = ($path{0} != '/');
        $isWindowsPath  = !(strpos($path, ':') === false);
    
        if (($isEmptyPath || $isRelativePath) && !$isWindowsPath)
            $path= getcwd().DIRECTORY_SEPARATOR.$path;
    
        // resolve path parts (single dot, double dot and double delimiters)
        $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
        $pathParts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
        $absolutePathParts = array();
        foreach ($pathParts as $part) {
            if ($part == '.')
                continue;
    
            if ($part == '..') {
                array_pop($absolutePathParts);
            } else {
                $absolutePathParts[] = $part;
            }
        }
        $path = implode(DIRECTORY_SEPARATOR, $absolutePathParts);
    
        // resolve any symlinks
        if (file_exists($path) && linkinfo($path)>0)
            $path = readlink($path);
    
        // put initial separator that could have been lost
        $path= (!$isWindowsPath ? '/'.$path : $path);
    
        return $path;
    }
    

提交回复
热议问题