Извлечение имени файла и пути в PHP: полное учебное пособие
Работа с именами и путями в PHP: извлечение имени файла и пути
В PHP существует несколько встроенных функций для работы с именами файлов и путями. Они позволяют выделить имя файла, расширение, директорию, преобразовать относительный путь в абсолютный и многое другое. Рассмотрим наиболее эффективные и распространённые способы, их цели и возможные проблемы.
Основное решение: функция pathinfo()
Функция pathinfo() возвращает ассоциативный массив с информацией о пути: dirname, basename, extension, filename. Это универсальный инструмент для любого разбора пути.
<?php
$path = '/var/www/html/index.php';
$info = pathinfo($path);
print_r($info);
?>имя php (имя в php)
Array
(
[dirname] => /var/www/html
[basename] => index.php
[extension] => php
[filename] => index
)При необходимости можно получить только одно значение, передав вторым аргументом константу: PATHINFO_DIRNAME, PATHINFO_BASENAME, PATHINFO_EXTENSION, PATHINFO_FILENAME.
Как получить только имя файла без пути? (basename)
Функция basename() возвращает последний компонент пути - имя файла (или папки). Если файл имеет расширение, оно включается в результат. Для удаления расширения можно передать второй параметр.
<?php
$path = '/images/photo.jpg';
echo basename($path); // photo.jpg
echo basename($path, '.jpg'); // photo
?>Возможная проблема:
На Windows basename() обрабатывает как прямой (/) так и обратный слеш (\), но на Linux только прямой слеш. Если путь приходит из внешнего источника, стоит привести разделители к одному виду.
Как получить директорию, содержащую файл? (dirname)
Функция dirname() возвращает родительскую директорию указанного пути. Если путь не содержит слешей, возвращает точку (.).
<?php
echo dirname('/etc/nginx/nginx.conf'); // /etc/nginx
echo dirname('file.txt'); // .
?>Как извлечь только расширение файла?
С помощью pathinfo($path, PATHINFO_EXTENSION) или substr(strrchr($path, '.'), 1). Первый способ предпочтительнее, так как он учитывает пустые расширения и точки в имени.
<?php
$path = 'archive.tar.gz';
echo pathinfo($path, PATHINFO_EXTENSION); // gz (заметно: вернёт только последнее расширение)
echo end(explode('.', $path)); // gz (но сломается, если нет точки)
?>Типичная ошибка:
Использование explode() или strrchr() для пути с точками в директории (например, /path.to/file.txt) приведёт к неверному результату. pathinfo() корректно обрабатывает такие случаи.
Как получить имя файла без расширения?
Используйте pathinfo($path, PATHINFO_FILENAME). Это самый надёжный способ.
<?php
$path = 'document.pdf';
echo pathinfo($path, PATHINFO_FILENAME); // document
$path2 = '/var/log/error.log';
echo pathinfo($path2, PATHINFO_FILENAME); // error
?>Как узнать абсолютный путь к текущему файлу? (__FILE__, __DIR__)
Магические константы __FILE__ и __DIR__ содержат полный путь и директорию текущего скрипта. __DIR__ эквивалентно dirname(__FILE__).
<?php
echo __FILE__; // /var/www/html/index.php
echo __DIR__; // /var/www/html
?>Как преобразовать относительный путь в абсолютный? (realpath)
realpath() возвращает канонизированный абсолютный путь, разрешая символические ссылки и удаляя лишние элементы (например, ..). Если путь не существует, возвращает false.
<?php
$relative = './../images/photo.jpg';
echo realpath($relative); // /var/www/images/photo.jpg (зависит от системы)
?>Возможная проблема:
Если целевой файл или директория не существуют, realpath() вернёт false. Для несуществующих путей используйте realpath(dirname($path)) . '/' . basename($path).
Расширенные примеры работы с именами и путями в PHP
1. Извлечение имени файла из URL (строки, похожей на путь)
Функции basename и pathinfo работают и с URL, если передать их как строку. Однако для сложных URL (с параметрами) сначала нужно выделить путь.
<?php
$url = 'https://example.com/img/photo.jpg?w=800';
$path = parse_url($url, PHP_URL_PATH);
echo basename($path); // photo.jpg
echo pathinfo($path, PATHINFO_FILENAME); // photo
?>photo.jpg photo
2. Обработка множественных расширений (например, .tar.gz)
pathinfo() возвращает только последнее расширение. Если нужно получить все части после первой точки, используйте explode или регулярное выражение.
<?php
$file = 'backup.tar.gz';
$parts = explode('.', $file);
$extensions = array_slice($parts, 1); // ['tar', 'gz']
echo implode('.', $extensions); // tar.gz
$name = $parts[0]; // backup
?>tar.gz backup
3. Получение списка файлов в директории с их именами без расширения
<?php
$dir = '/path/to/files';
$files = scandir($dir);
foreach ($files as $file) {
if (is_file($dir . '/' . $file)) {
$name = pathinfo($file, PATHINFO_FILENAME);
echo $name . PHP_EOL;
}
}
?>document image report
4. Безопасное построение пути с помощью DIRECTORY_SEPARATOR
<?php
$base = '/var/www';
$folder = 'uploads';
$file = 'file.txt';
$fullPath = $base . DIRECTORY_SEPARATOR . $folder . DIRECTORY_SEPARATOR . $file;
echo $fullPath; // /var/www/uploads/file.txt
// Для кросс-платформенности используйте DIRECTORY_SEPARATOR
?>/var/www/uploads/file.txt
5. Извлечение родительской директории несколько уровней вверх
Комбинируйте dirname() несколько раз или используйте realpath.
<?php
$path = '/a/b/c/d/file.txt';
$parent = dirname(dirname($path)); // '/a/b/c'
// Или через realpath:
$parent2 = realpath($path . '/../..'); // разрешит символические ссылки
?>/a/b/c
6. Получение имени файла без расширения из строки с путём (без pathinfo)
<?php
$path = '/var/log/app.log';
$basename = basename($path); // app.log
$dotPos = strrpos($basename, '.');
$filename = ($dotPos !== false) ? substr($basename, 0, $dotPos) : $basename;
echo $filename; // app
?>app
Проблема: не учтены случаи без расширения или имя начинается с точки (скрытые файлы).
Для скрытых файлов (например, .htaccess) strrpos вернёт 0, и substr даст пустую строку. Лучше использовать pathinfo, который возвращает filename как .htaccess.
7. Проверка существования файла и извлечение его имени
<?php
$path = '/etc/passwd';
if (file_exists($path)) {
$info = pathinfo($path);
echo 'Имя: ' . $info['filename'] . ', расширение: ' . $info['extension'];
} else {
echo 'Файл не найден';
}
?>Имя: passwd, расширение: