这应该是一个简单的问题,但我不记得相关的API。使用术语“combine directory name php”在Google上搜索不会产生任何结果。所以我想通过提出这个问题,我自己和编程社区都在做服务。
如何组合目录和文件名以在PHP中形成完整的文件路径?假设目录名称为“D:\setup program
”,文件名为“mj.txt
”。该方法应该在Windows“D:\setup program\mj.txt
”上返回给我。当然,该方法应该在Linux或其他操作系统中返回正确的文件路径。
.Net中的相关功能是Path.Combine,但在PHP中,我记不起来了,尽管我以前一定见过它。
答案 0 :(得分:34)
$filepath = $path . DIRECTORY_SEPARATOR . $file;
虽然在较新版本的PHP中,斜杠的方式无关紧要,但总是使用正斜杠也没关系。
您可以使用realpath()
获取正确的绝对路径,这也会删除诸如额外不必要的斜杠之类的内容并解析../
之类的引用。如果路径无效,它将返回false。
答案 1 :(得分:9)
我认为最干净,最灵活的方法是使用join函数和DIRECTORY_SEPARATOR常量:
$fullPath = join(DIRECTORY_SEPARATOR, array($directoryPath, $fileName));
答案 2 :(得分:1)
所有给出的答案都不会占用$directoryPath
中的空值,也不会处理重复的斜杠。虽然PHP确实具有很高的容错能力,但是第一点可能是致命的,如果您编写的是干净的代码,第二点也不应忽略。
因此正确的解决方案是:
function PathCombine($one, $other, $normalize = true) {
# normalize
if($normalize) {
$one = str_replace('/', DIRECTORY_SEPARATOR, $one);
$one = str_replace('\\', DIRECTORY_SEPARATOR, $one);
$other = str_replace('/', DIRECTORY_SEPARATOR, $other);
$other = str_replace('\\', DIRECTORY_SEPARATOR, $other);
}
# remove leading/trailing dir separators
if(!empty($one) && substr($one, -1)==DIRECTORY_SEPARATOR) $one = substr($one, 0, -1);
if(!empty($other) && substr($other, 0, 1)==DIRECTORY_SEPARATOR) $other = substr($other, 1);
# return combined path
if(empty($one)) {
return $other;
} elseif(empty($other)) {
return $one;
} else {
return $one.DIRECTORY_SEPARATOR.$other;
}
}
唯一的限制是第二个参数不能是绝对路径。
答案 3 :(得分:0)
这并不是您想要的,但是它应该得到一系列路径零件,然后使用DIRECTORY_SEPARATOR联接零件,然后使用DIRECTORY_SEPARATOR拆分联接零件并删除空的路径零件。它应该返回由DIRECTORY_SEPARATOR连接的其余路径部分。
function path_combine($paths) {
for ($i = 0; $i < count($paths); ++$i) {
$paths[$i] = trim($paths[$i]);
}
$dirty_paths = explode(DIRECTORY_SEPARATOR, join(DIRECTORY_SEPARATOR, $paths));
for ($i = 0; $i < count($dirty_paths); ++$i) {
$dirty_paths[$i] = trim($dirty_paths[$i]);
}
$unslashed_paths = array();
for ($i = 0; $i < count($dirty_paths); ++$i) {
$path = $dirty_paths[$i];
if (strlen($path) == 0) continue;
array_push($unslashed_paths, $path);
}
$first_not_empty_index = 0;
while(strlen($paths[$first_not_empty_index]) == 0) {
++$first_not_empty_index;
}
$starts_with_slash = $paths[$first_not_empty_index][0] == DIRECTORY_SEPARATOR;
return $starts_with_slash
? DIRECTORY_SEPARATOR . join(DIRECTORY_SEPARATOR, $unslashed_paths)
: join(DIRECTORY_SEPARATOR, $unslashed_paths);
}
用法示例:
$test = path_combine([' ', '/cosecheamo', 'pizze', '///// 4formaggi', 'GORGONZOLA']);
echo $test;
将输出:
/cosecheamo/pizze/4formaggi/GORGONZOLA
答案 4 :(得分:0)
尝试此功能。我使用此功能来满足自己的需求。
如果要检查路径,必须将$ isReal设置为true
public static function path($base, $com = null, $isReal = false)
{
if(substr($base, -1)!=DIRECTORY_SEPARATOR) $base.=DIRECTORY_SEPARATOR;
if($com) $base.=$com;
$base = preg_replace('/(\/+|\\\\+)/', DIRECTORY_SEPARATOR, $base);
while(preg_match('/(\/[\w\s_-]+\/\.\.)/', $base)){
$base = preg_replace('/(\/[\w\s_-]+\/\.\.)/', "", $base);
if(preg_match('/\/\.\.\//', $base))
throw new \Exception("Error directory don't have parent folder!", 1);
}
if($isReal){
$base = realpath($base);
if(is_dir($base)) $base .= DIRECTORY_SEPARATOR;
}
return $base;
}
示例输出:
var_dump(Combine::path("www///system", "Combine/../"));
// string(11) "www/system/"
var_dump(Combine::path("System", "Combine/../", true));
// string(40) "/home/snow/Desktop/localhost/www/System/"
var_dump(Combine::path("System", "Combine", true));
// string(48) "/home/snow/Desktop/localhost/www/System/Combine/"
var_dump(Combine::path("System", "Combine/notPath", true)); // if you try to create a path that does not exist
// bool(false)
var_dump(Combine::path("System", "Combine/class.Combine.php", true)); // you can also select a file
//string(65) "/home/snow/Desktop/localhost/www/System/Combine/class.Combine.php"
var_dump(Combine::path("/home/testuser\\badPath///////repair"));
// string(30) "/home/testuser/badPath/repair/"
答案 5 :(得分:0)
10年后,但这也许会帮助下一个。 这是我所做的使其与PHP 7.4+兼容的事情。
它与Path.Combine一样工作,除了字符串开头的\或/不会排除以前的参数。
class Path
{
public static function combine (): string
{
$paths = func_get_args();
$paths = array_map(fn($path) => str_replace(["\\", "/"], DIRECTORY_SEPARATOR, $path), $paths);
$paths = array_map(fn($path) => self::trimPath($path), $paths);
return implode(DIRECTORY_SEPARATOR, $paths);
}
private static function trimPath(string $path): string
{
$path = trim($path);
$start = $path[0] === DIRECTORY_SEPARATOR ? 1 : 0;
$end = $path[strlen($path) - 1] === DIRECTORY_SEPARATOR ? -1 : strlen($path);
return substr($path, $start, $end);
}
}
Path::combine("C:\Program Files", "/Repository", "sub-repository/folder/", "file.txt");
//return "C:\Program Files\Repository\sub-repository\folder\file.txt"
Path::combine("C:\Program Files", "/Repository/", "\\sub-repository\\folder\\", "sub-folder", "file.txt");
//return "C:\Program Files\Repository\sub-repository\folder\sub-folder\file.txt"
Path::combine("C:\file.txt");
//return "C:\file.txt"
Path::combine();
//return ""
答案 6 :(得分:-1)
你可以将它与php常量DIRECTORY_SEPARATOR
连接起来,或者只使用正斜杠。 Windows可能不介意= D