NaN*_*NaN 4 php class path relative-path absolute-path
是否有用于路径连接的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
Run Code Online (Sandbox Code Playgroud)
好的,这个例子有一个简单的解决方案,但是如果有不同的字典分隔符或某些路径有点复杂呢?
是否有现成的解决方案,如下所示:/home/uploads/../uploads/tmp =>/home/uploads/tmp ....
并行平台函数的平台无关版本如何?
相对路径应该以"./"作为前缀开头,还是"home/path/img /"常用方式?
如果该路径确实存在,您可以使用realpath
它来扩展它。
echo realpath("/home/../home/dogbert")
/home/dogbert
Run Code Online (Sandbox Code Playgroud)
我自己遇到了这个问题,主要是关于路径的规范化.
规范化是:
\\
)/../
/home/www/uploads//file.ext
我写了一个功能来实现这个目标.我现在无权访问该代码,但自己编写代码并不困难.
路径是否绝对对于这个规范化函数的实现并不重要,只需要注意领先的分隔符并且你很好.
我不太担心操作系统的依赖性.Windows和Linux PHP都理解/
为了简单起见我总是使用它 - 但我想你使用什么分隔符并不重要.
回答你的问题:如果你总是使用/
并假设一个目录没有尾随分隔符,那么路径连接可以非常简单.'没有尾随分隔符'似乎是一个很好的假设,因为dirname
删除尾随分隔符等功能.
然后它总是安全的:$dir . "/" . $file
.
即使结果路径/home/uploads/../uploads//my_uploads/myfile.ext
仍然可以正常工作.
当您需要在某处存储路径时,规范化变得很有用.而且因为你有这个规范化功能,你可以做出这些假设.
另一个有用的功能是制作相对路径的功能.
从这两个路径派生,文件的相对路径是什么是有用的.
真实路径
我发现realpath
性能非常重.如果你一次调用它就不是那么糟糕,但是如果你在一个循环中这样做你会受到很大影响.请记住,每次realpath
调用都是对文件系统的调用.而且,false
如果你传入一些愚蠢的东西,它会简单地返回,我宁愿让它抛出异常.
对我来说,该realpath
函数是BAD函数的一个很好的例子,因为它做了两件事:1.规范路径和2.它检查路径是否存在.这些功能当然都很有用,但它们必须分开.它也不区分文件和目录.对于Windows,这通常不是问题,但对于Linux它可以.
我认为realpath("")
在Windows上使用时有一些奇怪之处.我认为它会回归\\
- 这可能是非常不可接受的.
/**
* 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);
}
Run Code Online (Sandbox Code Playgroud)