Методы получения имени файла из пути в PHP: обзор и практика
Основные способы извлечения имени файла
Наиболее простой и эффективный способ получения имени файла из полного пути - функция basename(). Она возвращает последний компонент пути (имя файла) и опционально может удалить указанное расширение.
<?php
$path = '/var/www/html/images/photo.jpg';
$filename = basename($path);
echo $filename; // photo.jpg
?>
photo.jpg
Для извлечения имени без расширения второй параметр:
$nameWithoutExt = basename($path, '.jpg');
echo $nameWithoutExt; // photo
photo
Случаи использования: обработка путей из файловой системы, логирование, загрузка файлов (из $_FILES['file']['name']), извлечение имени из URL.
Проблемы и ошибки
- Передача пустой строки или null приводит к ошибке (PHP 8+ генерирует TypeError). Используйте проверку is_string().
- Если путь заканчивается слешем, basename может вернуть пустую строку или предыдущий компонент (зависит от системы). Всегда проверяйте результат.
- Функция не проверяет существование файла, она просто парсит строку.
Как получить имя файла и расширение по отдельности с помощью pathinfo?
Функция pathinfo() возвращает ассоциативный массив с ключами dirname, basename, extension (если есть) и filename (имя без расширения). Можно указать одну константу для получения конкретного элемента.
$info = pathinfo('/home/user/docs/report.txt');
echo $info['filename']; // report
echo $info['extension']; // txt
report txt
Постоянная PATHINFO_FILENAME и PATHINFO_EXTENSION:
$filename = pathinfo('/path/file.doc', PATHINFO_FILENAME);
echo $filename; // file
Возможные сложности
- Для файлов без расширения ключ extension будет отсутствовать или вернет пустую строку.
- Если путь содержит строку с точкой в имени каталога, pathinfo может некорректно выделить расширение. Например, '/path.to/file' - расширением может быть '.to/file'? На самом деле pathinfo корректно обрабатывает, но для абсолютной надежности лучше использовать basename в комбинации с explode('.').
Как использовать explode для извлечения имени файла?
Путь можно разделить по DIRECTORY_SEPARATOR (или слешу) и взять последний элемент массива.
$parts = explode('/', '/var/www/html/index.php');
$filename = end($parts);
echo $filename; // index.php
index.php
Для получения имени без расширения добавьте ещё explode по точке.
$parts = explode('/', $path);
$nameWithExt = end($parts);
$nameParts = explode('.', $nameWithExt);
$name = $nameParts[0]; // имя без расширения
echo $name;
Недостатки
- Не учитывается различие слешей в Windows/Unix. DIRECTORY_SEPARATOR может быть обратным слешем. Лучше использовать basename.
- Если в имени файла есть точки, explode('.') разобьет неправильно (например, 'archive.tar.gz' - получим 'archive'). Используйте pathinfo или preg_match.
Как извлечь имя файла из URL?
Сначала извлеките путь из URL с помощью parse_url(), затем примените basename.
$url = 'https://example.com/images/photo.jpg?size=large';
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
echo $filename; // photo.jpg
photo.jpg
Также можно удалить GET-параметры и якоря.
Проблемы
- URL может быть закодирован (например, %20). Для читаемого имени декодируйте с помощью urldecode() после basename.
- Некоторые URL содержат вложенные пути без имени файла (как '/' ). basename вернет пустую строку.
Как получить имена файлов из массива $_FILES?
При загрузке файла через форму изначальное имя хранится в $_FILES['field']['name']. Не доверяйте этому значению из-за возможной инъекции, но для вывода или логирования можно использовать.
$originalName = $_FILES['avatar']['name'];
$cleanName = basename($originalName);
echo $cleanName;
Используйте basename для фильтрации потенциальных путей (например, если злоумышленник передаст '../../etc/passwd').
Расширенные примеры извлечения имени файла
Извлечение имени из пути с произвольным разделителем
На Windows разделитель обратный слеш. Функция basename работает и с ним, но для надёжности можно использовать DIRECTORY_SEPARATOR.
$winPath = 'C:/Users/Doc/file.txt';
// Используем DIRECTORY_SEPARATOR
$parts = explode(DIRECTORY_SEPARATOR, $winPath);
$filename = end($parts);
echo $filename; // file.txt
// Также можно basename, он поддерживает оба вида слешей.
echo basename($winPath); // file.txt
file.txt file.txt
Получение имени без расширения для файлов с множественными точками
Для 'archive.tar.gz' pathinfo вернет extension = 'gz', filename = 'archive.tar'. Если нужно 'archive', используйте basename и удалите последнее расширение вручную.
$file = 'backup.tar.gz';
$base = basename($file); // backup.tar.gz
$dotPos = strrpos($base, '.');
if ($dotPos !== false) {
$nameWithoutExt = substr($base, 0, $dotPos);
} else {
$nameWithoutExt = $base;
}
echo $nameWithoutExt; // backup.tar
backup.tar
Обработка закодированных URL
$url = 'https://example.com/%D1%84%D0%BE%D1%82%D0%BE.jpg';
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
$decoded = urldecode($filename);
echo $decoded; // фото.jpg
фото.jpg
Использование DirectoryIterator для получения имён файлов в папке
$dir = '/var/www/html/uploads';
$iterator = new DirectoryIterator($dir);
$files = [];
foreach ($iterator as $fileinfo) {
if ($fileinfo->isFile()) {
$files[] = $fileinfo->getFilename(); // только имя файла
}
}
print_r($files);
Array ( [0] => image1.jpg [1] => document.pdf [2] => readme.txt )
Извлечение имени файла из пути с удалением GET-параметров
$url = 'http://example.com/download.php?file=report.pdf';
$path = parse_url($url, PHP_URL_PATH); // /download.php
$filename = basename($path);
// GET-параметры не попали в путь, поэтому безопасно.
echo $filename; // download.php
download.php
Получение последнего компонента пути с помощью array_slice и DIRECTORY_SEPARATOR
$path = '/home/user/projects/script.php';
$parts = explode('/', $path);
$filename = array_slice($parts, -1)[0];
echo $filename; // script.php
script.php