在 PHP 中组合目录和文件名(相当于 .Net 中的 Path.Combine)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1049949/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 00:47:25  来源:igfitidea点击:

Combine directory and file name in PHP ( equivalent of Path.Combine in .Net)

php

提问by Graviton

This should be a simple question, but I just can't recall the relevant API. A search on google with the term "combine directory name php" doesn't yield any results. So I guess I am doing both myself and the programming community a service by asking this question.

这应该是一个简单的问题,但我就是想不起来相关的 API。在 google 上使用“组合目录名称 php”一词进行搜索不会产生任何结果。所以我想我问这个问题是在为自己和编程社区提供服务。

How to combine directory and file name to form a full file path in PHP? Let's say the directory name is "D:\setup program", and the file name is "mj.txt". The method should return me, on Windows "D:\setup program\mj.txt". Of course the method should return the correct file path in Linux or other OS.

PHP中如何组合目录和文件名形成完整的文件路径?假设目录名为“ D:\setup program”,文件名为“ mj.txt”。该方法应该返回我,在 Windows 上“ D:\setup program\mj.txt”。当然,该方法在 Linux 或其他操作系统中应该返回正确的文件路径。

The related function in .Net is Path.Combine, but in PHP, I couldn't recall that, even though I must have seen it before.

.Net 中的相关函数是Path.Combine,但在 PHP 中,我想不起来了,即使我以前一定见过它。

回答by Tom Haigh

$filepath = $path . DIRECTORY_SEPARATOR . $file;

Although in newer versions of PHP it doesn't matter which way the slashes go, so it is fine to always use forward slashes.

尽管在较新版本的 PHP 中,斜杠的方向无关紧要,因此始终使用正斜杠是可以的。

You can get a correct absolute path using realpath(), this will also remove things like extra unnecessary slashes and resolve references like ../. It will return false if the path is not valid.

您可以使用 获得正确的绝对路径realpath(),这还将删除多余的不必要的斜杠等内容并解析../. 如果路径无效,它将返回 false。

回答by slashCoder

I think the most clean and flexible way to do it would be using the join function plus the DIRECTORY_SEPARATOR constant:

我认为最干净和灵活的方法是使用 join 函数加上 DIRECTORY_SEPARATOR 常量:

$fullPath = join(DIRECTORY_SEPARATOR, array($directoryPath, $fileName));

回答by jor

All given answers don't encouter empty values in the $directoryPathand don't handle duplicates slashes. While it is true that PHP is very error tolerant the first point can be fatal and the second point shouldn't be ignored if you're writing clean code.

所有给定的答案都不会在 中遇到空值$directoryPath,也不会处理重复的斜杠。虽然 PHP 确实非常容错,但第一点可能是致命的,如果您正在编写干净的代码,则不应忽略第二点。

So the correct solution is:

所以正确的解决方法是:

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;
    }

}

Only limitation is that the second parameter must not be an absolute path.

唯一的限制是第二个参数不能是绝对路径。

回答by user6307854

This is not exactly what you were looking for but it should get an array of path parts, then join the parts using DIRECTORY_SEPARATOR then split the joined parts using DIRECTORY_SEPARATOR and remove the empty path parts. It should return the remaining path parts joined by DIRECTORY_SEPARATOR.

这不是您要查找的内容,但它应该获取路径部分的数组,然后使用 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);
}

Example usage:

用法示例:

$test = path_combine([' ', '/cosecheamo', 'pizze', '///// 4formaggi', 'GORGONZOLA']);
echo $test;

Will output:

将输出:

/cosecheamo/pizze/4formaggi/GORGONZOLA

回答by Fatih Güven

Try this function. I use this function to meet my own needs.

试试这个功能。我使用这个功能来满足我自己的需求。

If you want to check the path, you must set $isReal to true

如果要检查路径,必须将 $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;
  }

Example output:

示例输出:

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/"

回答by Kantin Charignon

10 years later, but maybe this will help the next ones. Here's what I've done to make it compatible with PHP 7.4+.

10 年后,但也许这会对下一个有所帮助。这是我为使其与 PHP 7.4+ 兼容所做的工作。

It works just like Path.Combine except that the \ or / at the beginning of the string will not exclude the previous arguments.

它的工作原理与 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 ""

回答by Zenshai

You can just concatenate it with the php constant DIRECTORY_SEPARATOR, or just use forward slashes. Windows probably won't mind =D

您可以将它与 php 常量连接起来DIRECTORY_SEPARATOR,或者只使用正斜杠。Windows 可能不会介意 =D