显然,realpath非常容易出错。在PHP 5.3.1中,它会导致随机崩溃。在5.3.0及更低版本中,realpath会随机失败并返回false (当然,对于相同的字符串),而且它总是在realpath-ing上失败两次/更多次(当然,它第一次就能工作)。
此外,它在早期的PHP版本中有很多buggy,完全无法使用。Well...it已经是了,因为它不是一致的。
不管怎样,我有什么选择呢?也许我自己重写一下?这样做可取吗?
发布于 2010-10-29 17:04:26
感谢Sven Arduwie的代码(pointed out by Pekka)和一些修改,我构建了一个(希望)更好的实现:
/**
* 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。它仅适用于本地文件系统。
发布于 2015-03-31 23:25:39
下面是修改后的代码,也支持UNC路径
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;
}发布于 2013-12-05 16:19:14
我知道这是一个老帖子,但它真的很有帮助。
当我在phpctags中实现相对路径时,我遇到了一个奇怪的Phar::interceptFileFuncs问题,这个realpath()在phar中真的有很多buggy。
感谢这个线程给了我一些启发,下面是我基于这个线程和这个comments的christian实现的实现。
希望它能为你工作。
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;
}https://stackoverflow.com/questions/4049856
复制相似问题