首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >替换PHP的realpath()

替换PHP的realpath()
EN

Stack Overflow用户
提问于 2010-10-29 15:27:53
回答 6查看 25.6K关注 0票数 10

显然,realpath非常容易出错。在PHP 5.3.1中,它会导致随机崩溃。在5.3.0及更低版本中,realpath会随机失败并返回false (当然,对于相同的字符串),而且它总是在realpath-ing上失败两次/更多次(当然,它第一次就能工作)。

此外,它在早期的PHP版本中有很多buggy,完全无法使用。Well...it已经是了,因为它不是一致的。

不管怎样,我有什么选择呢?也许我自己重写一下?这样做可取吗?

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-10-29 17:04:26

感谢Sven Arduwie的代码(pointed out by Pekka)和一些修改,我构建了一个(希望)更好的实现:

代码语言:javascript
复制
/**
 * This function is to replace PHP's extremely buggy realpath().
 * @param string The original path, can be relative etc.
 * @return string The resolved path, it might not exist.
 */
function truepath($path){
    // whether $path is unix or not
    $unipath=strlen($path)==0 || $path{0}!='/';
    // attempts to detect if path is relative in which case, add cwd
    if(strpos($path,':')===false && $unipath)
        $path=getcwd().DIRECTORY_SEPARATOR.$path;
    // resolve path parts (single dot, double dot and double delimiters)
    $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;
        }
    }
    $path=implode(DIRECTORY_SEPARATOR, $absolutes);
    // resolve any symlinks
    if(file_exists($path) && linkinfo($path)>0)$path=readlink($path);
    // put initial separator that could have been lost
    $path=!$unipath ? '/'.$path : $path;
    return $path;
}

PHP NB:与realpath不同,这个函数在出错时不会返回false;它会返回一个尽可能远的路径来解决这些问题。

注2:显然有些人不能正确阅读。Truepath()不适用于网络资源,包括UNC和URL。它仅适用于本地文件系统。

票数 28
EN

Stack Overflow用户

发布于 2015-03-31 23:25:39

下面是修改后的代码,也支持UNC路径

代码语言:javascript
复制
static public function truepath($path)
{
    // whether $path is unix or not
    $unipath = strlen($path)==0 || $path{0}!='/';
    $unc = substr($path,0,2)=='\\\\'?true:false;
    // attempts to detect if path is relative in which case, add cwd
    if(strpos($path,':') === false && $unipath && !$unc){
        $path=getcwd().DIRECTORY_SEPARATOR.$path;
        if($path{0}=='/'){
            $unipath = false;
        }
    }

    // resolve path parts (single dot, double dot and double delimiters)
    $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;
        }
    }
    $path = implode(DIRECTORY_SEPARATOR, $absolutes);
    // resolve any symlinks
    if( function_exists('readlink') && file_exists($path) && linkinfo($path)>0 ){
        $path = readlink($path);
    }
    // put initial separator that could have been lost
    $path = !$unipath ? '/'.$path : $path;
    $path = $unc ? '\\\\'.$path : $path;
    return $path;
}
票数 4
EN

Stack Overflow用户

发布于 2013-12-05 16:19:14

我知道这是一个老帖子,但它真的很有帮助。

当我在phpctags中实现相对路径时,我遇到了一个奇怪的Phar::interceptFileFuncs问题,这个realpath()在phar中真的有很多buggy。

感谢这个线程给了我一些启发,下面是我基于这个线程和这个commentschristian实现的实现。

希望它能为你工作。

代码语言:javascript
复制
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;
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4049856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档