Определение названия файла в PHP: практические методы
Основные способы получения имени файла в PHP
Работа с именами файлов часто требуется при логировании, создании самоссылающихся ссылок или обработке загруженных данных. Рассмотрим различные подходы к извлечению имени файла из пути, включая наиболее эффективное решение и альтернативные варианты.
Наиболее универсальный способ получения имени текущего исполняемого PHP-файла — использовать константу __FILE__ вместе с функцией basename():
<?php
$filename = basename(__FILE__);
echo $filename; // index.php
?>Index php filename (имя файла в php)
Этот метод возвращает имя файла с расширением, независимо от того, включён ли файл через include или выполняется напрямую. Важно: __FILE__ всегда содержит полный путь к файлу, в котором она написана, поэтому basename корректно извлекает последний компонент.
Цель: получение имени текущего скрипта для логирования, самодиагностики или формирования ссылок.
Проблема: если файл включён через include из другой директории, __FILE__ покажет путь к включённому файлу, а не к основному скрипту. Решение: использовать $_SERVER['SCRIPT_FILENAME'] для получения пути к основному скрипту.
Как получить имя файла из произвольного пути?
Функция basename() принимает строку пути и возвращает имя файла (последний компонент).
<?php
$path = '/var/www/html/project/index.php';
$filename = basename($path);
echo $filename; // index.php
?>
Это полезно при обработке списка файлов, полученных из glob() или scandir().
Проблема: basename() чувствительна к локали. Если путь содержит многобайтовые символы (например, кириллица), результат может быть обрезан. Решение: установить локаль setlocale(LC_CTYPE, 'UTF-8').
Как получить имя файла без расширения?
Функция pathinfo() с константой PATHINFO_FILENAME извлекает только имя без расширения.
<?php
$path = 'document.txt';
$name = pathinfo($path, PATHINFO_FILENAME);
echo $name; // document
?>
Это удобно для создания временных файлов или проверки базового имени.
Проблема: если в имени файла несколько точек (например, file.tar.gz), PATHINFO_FILENAME вернёт только 'file.tar'. Решение: использовать explode() с проверкой последнего сегмента.
Как получить только расширение файла?
С помощью pathinfo() и PATHINFO_EXTENSION можно извлечь расширение.
<?php
$path = 'image.jpg';
$ext = pathinfo($path, PATHINFO_EXTENSION);
echo $ext; // jpg
?>
Применяется для фильтрации типов файлов при загрузке.
Проблема: расширение может отсутствовать. В таком случае возвращается пустая строка. Решение: проверять результат и обрабатывать как отдельный случай.
Как получить имя скрипта, вызванного через URL?
Суперглобальные переменные $_SERVER['SCRIPT_NAME'] или $_SERVER['PHP_SELF'] содержат путь от корня веб-сервера до текущего скрипта. basename() выделяет имя.
<?php
$script = basename($_SERVER['SCRIPT_NAME']);
echo $script; // index.php
?>
Подходит для создания форм с действием на себя или ссылок на текущую страницу.
Проблема: $_SERVER['PHP_SELF'] уязвим к XSS, если URL содержит манипуляции. Решение: использовать $_SERVER['SCRIPT_NAME'] или фильтровать через htmlspecialchars().
Как получить имя файла из полного пути с нормализацией?
Функция realpath() преобразует путь в канонический абсолютный путь, после чего можно применить basename().
<?php
$relative = './../test/../folder/file.php';
$normalized = realpath($relative);
$filename = basename($normalized);
echo $filename; // file.php
?>
Помогает избежать ошибок, связанных с символическими ссылками или относительными путями.
Проблема: realpath() возвращает false, если файл не существует. Решение: проверять результат перед использованием.
Как извлечь имя файла из URL (не локального пути)?
Для URL можно использовать parse_url() и затем basename().
<?php
$url = 'https://example.com/images/photo.jpg';
$path = parse_url($url, PHP_URL_PATH);
$filename = basename($path);
echo $filename; // photo.jpg
?>
Применяется при парсинге внешних ресурсов.
Расширенные примеры работы с именем файла
Извлечение имени без расширения для файлов с несколькими точками
Файлы типа archive.tar.gz требуют особого подхода, так как стандартное расширение — последняя часть после последней точки. Чтобы получить имя до первого расширения, можно использовать strpos().
<?php
$filename = 'backup.tar.gz';
$dotPos = strpos($filename, '.');
$base = ($dotPos === false) ? $filename : substr($filename, 0, $dotPos);
echo $base; // backup
?>
Output: backup
Для получения только последнего расширения удобнее pathinfo():
<?php
$ext = pathinfo('backup.tar.gz', PATHINFO_EXTENSION);
echo $ext; // gz
?>
Output: gz
Объектно-ориентированное получение имени файла через SplFileInfo
Класс SplFileInfo предоставляет методы getBasename(), getFilename(), getExtension() и getPath().
<?php
$file = new SplFileInfo('/var/www/html/app/config.php');
echo $file->getBasename(); // config.php
echo $file->getFilename(); // config.php
echo $file->getExtension(); // php
echo $file->getPath(); // /var/www/html/app
?>
config.php config.php php /var/www/html/app
Этот подход удобен в ООП-стиле, особенно при работе с итераторами.
Получение имен всех файлов в директории с помощью DirectoryIterator
Использование итератора позволяет получить имена файлов без расширений.
<?php
$dir = new DirectoryIterator('./uploads');
foreach ($dir as $fileInfo) {
if ($fileInfo->isFile()) {
echo $fileInfo->getBasename('.txt') . PHP_EOL;
}
}
?>
file1 file2 notes
Метод getBasename($suffix) отсекает указанное расширение.
Обработка путей с разными разделителями (Windows vs Unix)
Константа DIRECTORY_SEPARATOR помогает писать кросс-платформенный код. Можно использовать basename(), который корректно работает с обоими разделителями.
<?php
$winPath = 'C:\\Users\\Admin\\file.php';
$unixPath = '/home/user/file.php';
echo basename($winPath); // file.php
echo basename($unixPath); // file.php
?>
file.php file.php
Извлечение имени файла из пользовательского ввода с безопасной фильтрацией
При обработке загрузок нельзя доверять имени файла напрямую. Лучше извлечь безопасное имя через basename() и удалить недопустимые символы.
<?php
$userInput = '../../../etc/passwd';
$safe = basename($userInput);
$safe = preg_replace('/[^a-zA-Z0-9._-]/', '_', $safe);
echo $safe; // passwd
// Примечание: имя 'passwd' без расширения, так как исходное имя не содержало расширения
?>
passwd
Такая фильтрация предотвращает Path Traversal атаки.
Сравнение производительности basename vs explode
Для больших массивов путей basename() обычно быстрее, но можно использовать explode() с последним элементом.
<?php
$paths = ['/a/b/c.php', '/d/e/f.html', '/g/h/i.txt'];
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
foreach ($paths as $p) {
$b = basename($p);
}
}
echo 'basename: ' . (microtime(true) - $start) . " s\n";
$start = microtime(true);
for ($i = 0; $i < 10000; $i++) {
foreach ($paths as $p) {
$parts = explode('/', $p);
$b = end($parts);
}
}
echo 'explode: ' . (microtime(true) - $start) . " s\n";
?>
basename: 0.015 s explode: 0.022 s
Результаты могут варьироваться, но basename() оптимизирована на уровне C.