2011-07-24 61 views
4

是否有PHP内部函数用于路径连接?我有什么可能合并几条路径(绝对和相对)。PHP连接的路径

//Example: 
$path1="/usr/home/username/www"; 
$path2="domainname"; 
$path3="images/thumbnails"; 
$domain="exampledomain.com"; 

//As example: Now I want to create a new path (domain + path3) on the fly. 
$result = $domain.DIRECTORY_SEPARATOR.$path3 

好,对于这个例子简单的解决方案,但如果有不同的字典分离器或一些路径是有点复杂?

有一个现有的解决方案,修剪它是这样的:/home/uploads/../uploads/tmp => /家/上传/ tmp目录....

?如何独立于平台的版本一个路径连接函数的外观如何?

相对路径应该以“./”作为前缀开始,还是以“home/path/img /”为常用方式?

回答

5

我碰到这个问题我自己,主要是关于路径正常化

规范化是:

  • 一个分离器(我选择了支持,但永远不会返回向后斜线\\
  • 解决间接:/../
  • 删除重复分隔符:/home/www/uploads//file.ext
  • 始终删除尾随分隔符。

我已经写了一个实现这个功能。我目前无法访问该代码,但自己编写代码也并不难。

对于这个规范化函数的实现,路径是否是绝对的并不重要,只要注意领先的分隔符并且你很好。

我并不太担心操作系统的依赖。 Windows和Linux PHP都明白/,所以为了简单起见,我只是总是使用它 - 但我想这与你使用的分隔符无关。


要回答你的问题:路径的级联可以很容易的,如果你只是总是使用/假设一个目录没有尾随分隔符。 '没有尾随分隔符'似乎是一个好的假设,因为像dirname这样的函数删除尾随分隔符。

然后它总是安全的做:$dir . "/" . $file

即使结果路径是/home/uploads/../uploads//my_uploads/myfile.ext它仍然会正常工作。

当您需要将路径存储在某处时,标准化将变得非常有用。因为你有这个规范化函数,你可以做出这些假设。


另一个有用的函数是一个函数,用于生成相对路径。

  • /文件/上传
  • /files/uploads/my_uploads/myfile.ext

它可以是这两个路径获得有用的,该文件的相对路径是什么。


真实路径

我发现realpath是非常沉重的性能。如果你只是一次调用它,那么它并不是那么糟糕,但如果你在一个循环的某个地方做这件事,你会得到相当大的一击。请记住,每个realpath调用也是对文件系统的调用。另外,如果你传入一些愚蠢的东西,它会简单地返回false,我宁愿让它抛出异常。

对我来说,realpath功能是BAD功能的一个很好的例子,因为它做了两两件事:1,规范化的路径和2.它检查是否存在的路径。这两个功能当然都有用,但它们必须分开。它也不区分文件和目录。对于Windows来说,这通常不是问题,但对于Linux来说可以。

而且我认为在Windows上使用realpath("")会有一些奇特的性质。我想它会返回\\ - 这可能是非常不可接受的。


/** 
* This function is a proper replacement for realpath 
* It will _only_ normalize the path and resolve indirections (.. and .) 
* Normalization includes: 
* - directiory separator is always/
* - there is never a trailing directory separator 
* @param $path 
* @return String 
*/ 
function normalize_path($path) { 
    $parts = preg_split(":[\\\/]:", $path); // split on known directory separators 

    // resolve relative paths 
    for ($i = 0; $i < count($parts); $i +=1) { 
     if ($parts[$i] === "..") {   // resolve .. 
      if ($i === 0) { 
       throw new Exception("Cannot resolve path, path seems invalid: `" . $path . "`"); 
      } 
      unset($parts[$i - 1]); 
      unset($parts[$i]); 
      $parts = array_values($parts); 
      $i -= 2; 
     } else if ($parts[$i] === ".") { // resolve . 
      unset($parts[$i]); 
      $parts = array_values($parts); 
      $i -= 1; 
     } 
     if ($i > 0 && $parts[$i] === "") { // remove empty parts 
      unset($parts[$i]); 
      $parts = array_values($parts); 
     } 
    } 
    return implode("/", $parts); 
} 

/** 
* Removes base path from longer path. The resulting path will never contain a leading directory separator 
* Base path must occur in longer path 
* Paths will be normalized 
* @throws Exception 
* @param $base_path 
* @param $longer_path 
* @return string normalized relative path 
*/ 
function make_relative_path($base_path, $longer_path) { 
    $base_path = normalize_path($base_path); 
    $longer_path = normalize_path($longer_path); 
    if (0 !== strpos($longer_path, $base_path)) { 
     throw new Exception("Can not make relative path, base path does not occur at 0 in longer path: `" . $base_path . "`, `" . $longer_path . "`"); 
    } 
    return substr($longer_path, strlen($base_path) + 1); 
} 
+0

+1,但构建一组新零件非常容易。保存整个索引并进行大量计算。 –

4

如果路径实际存在,您可以使用realpath来扩展它。

echo realpath("/home/../home/dogbert") 
/home/dogbert 
+0

好的,这相当酷,但是有没有办法来找出目录分隔符或有一个标准化的路径“格式”? – NaN

0

与真实路径的另一问题是,它不与网址工作的,但串接的逻辑是基本相同的(应该有正好一个斜线之间的两个相结合的成分)。很明显,在开头有两个斜杠的协议部分是这个规则的例外。但是,将一个URL加入到一起的函数将会非常好。