Home » Php » Combine Directory and File Name in PHP ( equivalent of Path.Combine in .Net)

Combine Directory and File Name in PHP ( equivalent of Path.Combine in .Net)

Posted by: admin April 23, 2020 Leave a comment

Questions:

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.

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.

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

How to&Answers:
$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.

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.

Answer:

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

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

Answer:

All given answers don’t encouter empty values in the $directoryPath and 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.

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.

Answer:

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

Answer:

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.

 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

Answer:

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

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