Intereting Posts
PHP-эквивалент объектов ASP.NET Application / Cache bcdiv с очень маленьким поплавком с научной нотацией вызывает ошибку «Деление на ноль» nodeJS и PHP (Laravel) для горячего чата Socket.IO Предупреждение: trim () ожидает, что параметр 1 будет строкой, массив указан в wp-includes / class-phpmailer.php в строке 973 Настройка сервера LocalHost для MacOS Sierra для использования PHP и apache установить кодировку utf-8 для fread fread PHP-скрипт для преобразования нескольких изображений в видео с помощью imagick Ток обновления для Google-api-php возвращает invalid_grant Каков синтаксис сортировки коллекции Eloquent несколькими столбцами? Не удается подключиться к базе данных (000webhost) PHPDoc для массивов аргументов переменной длины вызов функции php в javascript Лучший способ справиться с ошибками в полнотекстовом поиске MySQL PHP SOAP Перенос файлов PHP: анализ разделенных запятыми значений между квадратными скобками в многомерном массиве

Как присоединиться к строкам пути файловой системы в PHP?

Есть встроенная функция в PHP для интеллектуального объединения строк пути? Функция, заданная как «abc / de /» и «/fg/x.php» в качестве аргументов, должна возвращать «abc / de / fg / x.php»; тот же результат должен быть задан с использованием «abc / de» и «fg / x.php» в качестве аргументов для этой функции.

Если нет, есть ли доступный класс? Это также может быть полезно для расщепления путей или удаления их частей. Если вы что-то написали, можете ли вы поделиться своим кодом здесь?

Всегда хорошо использовать «/», я кодирую только для Linux.

В Python есть os.path.join() , что отлично.

Поскольку это, кажется, популярный вопрос, и комментарии заполняются «предложениями об особенностях» или «отчетами об ошибках» … Весь этот фрагмент кода – это объединение двух строк с косой чертой без дублирования косых черт между ними. Это все. Не больше, не меньше. Он не оценивает фактические пути на жестком диске и фактически не сохраняет начальную косую черту (добавьте обратно, если необходимо), по крайней мере, вы можете быть уверены, что этот код всегда возвращает строку без запуска косой черты).

 join('/', array(trim("abc/de/", '/'), trim("/fg/x.php", '/'))); 

Конечным результатом всегда будет путь без косой черты в начале или конце и без двойных косых черт. Не стесняйтесь делать из этого функцию.

EDIT: Вот хорошая гибкая функциональная оболочка для вышеописанного фрагмента. Вы можете передать столько фрагментов пути, сколько хотите, либо как массив или отдельные аргументы:

 function joinPaths() { $args = func_get_args(); $paths = array(); foreach ($args as $arg) { $paths = array_merge($paths, (array)$arg); } $paths = array_map(create_function('$p', 'return trim($p, "/");'), $paths); $paths = array_filter($paths); return join('/', $paths); } echo joinPaths(array('my/path', 'is', '/an/array')); //or echo joinPaths('my/paths/', '/are/', 'a/r/g/u/m/e/n/t/s/'); 

: О)

 function join_paths() { $paths = array(); foreach (func_get_args() as $arg) { if ($arg !== '') { $paths[] = $arg; } } return preg_replace('#/+#','/',join('/', $paths)); } 

Мое решение проще и более похоже на то, как работает Python os.path.join

Рассмотрите эти тестовые примеры

 array my version @deceze @david_miller @mark ['',''] '' '' '/' '/' ['','/'] '/' '' '/' '/' ['/','a'] '/a' 'a' '//a' '/a' ['/','/a'] '/a' 'a' '//a' '//a' ['abc','def'] 'abc/def' 'abc/def' 'abc/def' 'abc/def' ['abc','/def'] 'abc/def' 'abc/def' 'abc/def' 'abc//def' ['/abc','def'] '/abc/def' 'abc/def' '/abc/def' '/abc/def' ['','foo.jpg'] 'foo.jpg' 'foo.jpg' '/foo.jpg' '/foo.jpg' ['dir','0','a.jpg'] 'dir/0/a.jpg' 'dir/a.jpg' 'dir/0/a.jpg' 'dir/0/a.txt' 

Функция @ deceze не удерживает лидерство / при попытке присоединиться к пути, который начинается с абсолютного пути Unix, например joinPaths('/var/www', '/vhosts/site'); ,

 function unix_path() { $args = func_get_args(); $paths = array(); foreach($args as $arg) { $paths = array_merge($paths, (array)$arg); } foreach($paths as &$path) { $path = trim($path, '/'); } if (substr($args[0], 0, 1) == '/') { $paths[0] = '/' . $paths[0]; } return join('/', $paths); } 

Мой прием:

 function trimds($s) { return rtrim($s,DIRECTORY_SEPARATOR); } function joinpaths() { return implode(DIRECTORY_SEPARATOR, array_map('trimds', func_get_args())); } 

Я бы использовал анонимную функцию для trimds , но более старые версии PHP не поддерживают ее.

Пример:

 join_paths('a','\\b','/c','d/','/e/','f.jpg'); // a\b\c\d\e\f.jpg (on Windows) 

Обновить апрель 2013 Март 2014 :

 function join_paths() { return preg_replace('~[/\\\]+~', DIRECTORY_SEPARATOR, implode(DIRECTORY_SEPARATOR, func_get_args())); } 

Это позволит исправить любые косые черты, соответствующие вашей ОС, не удалит ведущую косую черту, а также очистит и несколько косых черт в строке.

Альтернативой является использование implode() и explode() .

 $a = '/a/bc/def/'; $b = '/q/rs/tuv/path.xml'; $path = implode('/',array_filter(explode('/', $a . $b))); echo $path; // -> a/bc/def/q/rs/tuv/path.xml 

для получения частей путей вы можете использовать pathinfo http://nz2.php.net/manual/en/function.pathinfo.php

для присоединения ответа от @deceze выглядит отлично

Другой способ атаковать этот:

 function joinPaths() { $paths = array_filter(func_get_args()); return preg_replace('#/{2,}#', '/', implode('/', $paths)); } 

Это скорректированная версия функции, отправленной с помощью deceze. Без этого изменения joinPaths ('', 'foo.jpg') становится '/foo.jpg'

 function joinPaths() { $args = func_get_args(); $paths = array(); foreach ($args as $arg) $paths = array_merge($paths, (array)$arg); $paths2 = array(); foreach ($paths as $i=>$path) { $path = trim($path, '/'); if (strlen($path)) $paths2[]= $path; } $result = join('/', $paths2); // If first element of old path was absolute, make this one absolute also if (strlen($paths[0]) && substr($paths[0], 0, 1) == '/') return '/'.$result; return $result; } 

Если вы знаете, что файл / каталог существует, вы можете добавить дополнительные косые черты (что может быть ненужным), а затем вызвать realpath, т.е.

realpath(join('/', $parts));

Это, конечно, не совсем то же самое, что и версия Python, но во многих случаях может быть достаточно хорошей.

Кажется, это работает очень хорошо, и выглядит довольно аккуратно для меня.

 private function JoinPaths() { $slash = DIRECTORY_SEPARATOR; $sections = preg_split( "@[/\\\\]@", implode('/', func_get_args()), null, PREG_SPLIT_NO_EMPTY); return implode($slash, $sections); } 

Лучшее решение найдено:

 function joinPaths($leftHandSide, $rightHandSide) { return rtrim($leftHandSide, '/') .'/'. ltrim($rightHandSide, '/'); } 

ПРИМЕЧАНИЕ. Скопировано из комментария пользователя89021

Вот функция, которая ведет себя как path.resolve узла path.resolve :

 function resolve_path() { $working_dir = getcwd(); foreach(func_get_args() as $p) { if($p === null || $p === '') continue; elseif($p[0] === '/') $working_dir = $p; else $working_dir .= "/$p"; } $working_dir = preg_replace('~/{2,}~','/', $working_dir); if($working_dir === '/') return '/'; $out = []; foreach(explode('/',rtrim($working_dir,'/')) as $p) { if($p === '.') continue; if($p === '..') array_pop($out); else $out[] = $p; } return implode('/',$out); } 

Тестовые случаи:

 resolve_path('/foo/bar','./baz') # /foo/bar/baz resolve_path('/foo/bar','/tmp/file/') # /tmp/file resolve_path('/foo/bar','/tmp','file') # /tmp/file resolve_path('/foo//bar/../baz') # /foo/baz resolve_path('/','foo') # /foo resolve_path('/','foo','/') # / resolve_path('wwwroot', 'static_files/png/', '../gif/image.gif') # __DIR__.'/wwwroot/static_files/gif/image.gif' 

Из большого ответа Рикардо Галли, немного улучшения, чтобы избежать убийства протокола префикса.

Идея состоит в том, чтобы проверить наличие протокола в одном аргументе и сохранить его в результате. ПРЕДУПРЕЖДЕНИЕ: это наивная реализация!

Например:

 array("http://domain.de","/a","/b/") 

результаты (протокол ведения)

 "http://domain.de/a/b/" 

вместо (протокол убийства)

 "http:/domain.de/a/b/" 

Но http://codepad.org/hzpWmpzk нуждается в лучшем навыке написания кода.

Мне понравилось несколько представленных решений. Но те, кто заменяет все «/ +» на «/» (регулярные выражения), забывают, что os.path.join () из python может обрабатывать такой тип соединения:

 os.path.join('http://example.com/parent/path', 'subdir/file.html') 

Результат: ' http://example.com/parent/path/subdir/file.html '