Компонент Filesystem
Дата обновления перевода: 2024-07-03
Компонент Filesystem
Компонент Filesystem предоставляет независимые от платформ инструменты для операций файловых систем и для манипуляций с путями файлов/каталогов.
Установка
1
$ composer require symfony/filesystem
Note
Если вы устанавливаете этот компонент вне приложения Symfony, вам нужно
подключить файл vendor/autoload.php
в вашем коде для включения механизма
автозагрузки классов, предоставляемых Composer. Детальнее читайте в
этой статье.
Использование
Компонент содержит два основных класса, под названиями Filesystem и Path:
1 2 3 4 5 6 7 8 9 10 11 12 13
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Filesystem\Path;
$filesystem = new Filesystem();
try {
$filesystem->mkdir(
Path::normalize(sys_get_temp_dir().'/'.random_int(0, 1000)),
);
} catch (IOExceptionInterface $exception) {
echo "An error occurred while creating your directory at ".$exception->getPath();
}
Утилиты файловой системы
mkdir
mkdir() создаёт каталог
рекурсивно. В файловых системах POSIX, каталоги создаются со значением режима
по умолчанию 0777
. Вы можете использовать второй аргумент, чтобы установить
ваш собственный режим:
1
$fileSystem->mkdir('/tmp/photos', 0700);
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
Note
Эта функция игнорирует уже существующие каталоги.
exists
exists() проверяет наличие
одного или болеефайлоа или каталогов и возвращает false
, если какие-либо
из них отсутствуют:
1 2 3 4 5 6
// если этот каталог с этим абсолютным путём существует, вернуть true
$fileSystem->exists('/tmp/photos');
// если rabbit.jpg существует, bottle.png не существует, вернуть false
// не абсолютные пути являются относительными к каталогу, где находится запущенный скрипт PHP
$fileSystem->exists(array('rabbit.jpg', 'bottle.png'));
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
copy
copy() делает копию одного файла (используйте mirror(), чтобы копировать каталоги). Если цель уже существует, то файл копируется только, если дата изменения источника позже, чем у цели. Это поведение можно переопределить третьим булевым аргументом:
1 2 3 4 5
// работает только, если image-ICC было изменено после image.jpg
$fileSystem->copy('image-ICC.jpg', 'image.jpg');
// image.jpg будет переопределено
$fileSystem->copy('image-ICC.jpg', 'image.jpg', true);
touch
touch() устанавливает доступ и время изменения файла. Текущее время используется по умолчанию. Вы можете установить ваше собственное с помощью второго аргумента. Третий аргумент - это время доступа:
1 2 3 4 5 6
// устанавливает время изменения в текущей отметке времени
$fileSystem->touch('file.txt');
// устанавливает время изменения на 10 секунд в будущем
$fileSystem->touch('file.txt', time() + 10);
// устанавливает время изменения на 10 секунд в прошлом
$fileSystem->touch('file.txt', time(), time() - 10);
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
chown
chown() изменяет владельца файла. Третий аргумент - рекурсивная булева опция:
1 2 3 4
// устанавливает владельца видео lolcat как www-data
$fileSystem->chown('lolcat.mp4', 'www-data');
// рекурсивно изменяет владельца каталога видео
$fileSystem->chown('/video', 'www-data', true);
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
chgrp
chgrp() изменяет группу файла. Третий аргумент - рекурсивная булева опция:
1 2 3 4
// устанавливает группу видео lolcat как nginx
$fileSystem->chgrp('lolcat.mp4', 'nginx');
// рекурсивно изменяет группу каталога видео
$fileSystem->chgrp('/video', 'nginx', true);
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
chmod
chmod() изменяет режим или разрешения файла. Четвертый аргумент - рекурсивная булева опция:
1 2 3 4
// устанавливает режим видео 0600
$fileSystem->chmod('video.ogg', 0600);
// рекурсивно изменяет режим каталога src
$fileSystem->chmod('src', 0700, 0000, true);
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
remove
remove() удаляет файлы, каталогы и сивольные ссылки:
1
$fileSystem->remove(array('symlink', '/path/to/directory', 'activity.log'));
Note
Вы можете передать массив или любой traversable объект в качестве первого аргумента.
rename
rename() изменяет имя одного файла или каталога:
1 2 3 4 5 6
// переименовывает файл
$fileSystem->rename('/tmp/processed_video.ogg', '/path/to/store/video_647.ogg');
// переименовывает каталог
$fileSystem->rename('/tmp/files', '/path/to/store/files');
// если цель уже существует, для перезаписи доступен третий булев аргумент.
$filesystem->rename('/tmp/processed_video2.ogg', '/path/to/store/video_647.ogg', true);
symlink
symlink() создаёт символьную ссылку от цели к направлению. Если файловая система не поддерживает символьные ссылки, доступен третий булев аргумент:
1 2 3 4 5
// создаёт символьную ссылку
$fileSystem->symlink('/path/to/source', '/path/to/destination');
// дублирует каталог источника, если файловая система
// не поддерживает символьные ссылки
$fileSystem->symlink('/path/to/source', '/path/to/destination', true);
readlink
readlink() читает ссылки целей.
Метод readlink(), предоставленные компонентом Filesystem всегда ведёт себя одинаково на всех операционных системах (в отличие от функции PHP readlink):
1 2 3 4 5 6
// возвращает следующую прямую цель ссылки, не рассматривая существование цели
$fileSystem->readlink('/path/to/link');
// возвращает абсолютнуюп полностью разрешённую финальную версию цели
// (если были вложенные ссылки, они разрешены)
$fileSystem->readlink('/path/to/link', true);
Его поведение следующее:
1
public function readlink($path, $canonicalize = false)
- Когда
$canonicalize
-false
: -
- если
$path
не существует, или не является ссылкой, то возвращаетсяnull
. - если
$path
- ссылка, возвращается следующая прямая цель ссылки, не рассматривая существование цели.
- если
- Когда
- Когда
$canonicalize
-true
: -
- если
$path
не существует, то возвращаетсяnull
. - если
$path
существует, то возвращается его абсолютная полностью разрешённая финальная версия.
- если
- Когда
Note
Если вы хотите каноникализировать путь, не проверяя его существование, вы можете использовать вместо этого метод canonicalize().
makePathRelative
makePathRelative() берёт два абсолютных пути и возвращает относительный путь от второго пути к первому:
1 2 3 4 5 6 7
// возвращает '../'
$fileSystem->makePathRelative(
'/var/lib/symfony/src/Symfony/',
'/var/lib/symfony/src/Symfony/Component'
);
// возвращает 'videos/'
$fileSystem->makePathRelative('/tmp/videos', '/tmp')
mirror
mirror() копирует всё содержание каталога источника в целевой (используйте метод copy(), чтобы скопировать одиночные файлы):
1
$fileSystem->mirror('/path/to/source', '/path/to/target');
isAbsolutePath
isAbsolutePath() возвращает
true
, если данный путь абсолютный, false
- во всех других случаях:
1 2 3 4 5 6 7 8
// возвращает true
$fileSystem->isAbsolutePath('/tmp');
// возвращает true
$fileSystem->isAbsolutePath('c:\\Windows');
// возвращает false
$fileSystem->isAbsolutePath('tmp');
// возвращает false
$fileSystem->isAbsolutePath('../dir');
tempnam
tempnam() создает временный файл с уникальным именем, и возвращает его путь, или вызывает исключение при неудаче:
1 2 3 4
// возвращает путь вроде : /tmp/prefix_wyjgtF
$filesystem->tempnam('/tmp', 'prefix_');
// возвращает путь вроде : /tmp/prefix_wyjgtF.png
$filesystem->tempnam('/tmp', 'prefix_', '.png');
dumpFile
dumpFile() сохраняет данное содержание в файл. Это делается автоматически: он вначале записывает временный файл и потом перемещает его в новую локацию файла, когда он закончен. Это означает, что пользовательвсегда будет видеть либо полный старый файл, либо полный новый файл (но никогда - частично написанный файл):
1
$fileSystem->dumpFile('file.txt', 'Hello World');
Файл file.txt
теперь содержит Hello World
.
appendToFile
appendToFile() добавляет новое содержание в конце некоторого файла:
1 2 3
$fileSystem->appendToFile('logs.txt', 'Email sent to user@example.com');
// третий аргумент сообщает, должен ли файл снова быть заблокирован при внесении записей в него
$filesystem->appendToFile('logs.txt', 'Email sent to user@example.com', true);
Если либо файл, либо каталог, содержащий его, не существует, то этот метод создаёт их перед добавлением содержания.
readFile
7.1
Метод readFile()
был представлен в Symfony 7.1.
readFile() возвращает все содержимое файла в виде строки. В отличие от функции file_get_contents из PHP, она вызывает исключение, если заданный путь к файлу не читается и при передаче пути к каталогу вместо файла:
1
$contents = $filesystem->readFile('/some/path/to/file.txt');
Переменная $contents
теперь хранит все содержание файла file.txt
.
Утилиты для манипуляций с путями
Работа с путями файлов обычно вызывает некоторые сложности:
- Разница платформ: пути файлов выглядят по-разному на разных платформах. Пути файлов UNIX начинаются со слеша ("/"), в то время, как пути файлов Windows начинаются с систмного диска ("C:"). UNIX использует слеш вправо, в то время, как Windows по умолчанию использует слеш влево.
- Абсолютные/относительные пути: веб-приложениям часто необходимо разбираться с абсолютными и относительными путями. Преобразование одних в другие правильным образом является сложным и утомительным.
Path предоставляет служебные методы для работы с такими проблемами.
Каноникализация
Возвращает самое короткое имя пути, эквивалентное заданному пути. Итеративно применяет следующие правила до тех пор, пока дальнейшая обработка не станет невозможной:
- удаляются сегменты ".";
- разрешаются сегменты "..";
- слеши влево ("") преобразуются в слеши вправо ("/");
- корневые пути ("/" и "C:/") всегда заканчиваются слешем;
- некорневые пути никогда не заканчиваются слешем;
- схемы (такие, как "phar://") остаются;
~
заменяются домашним каталогом пользователя.
Вы можете каноникализировать путь с помощью canonicalize():
1 2
echo Path::canonicalize('/var/www/vhost/webmozart/../config.ini');
// => /var/www/vhost/config.ini
Вы можете передать абсолютные и относительные пути методу canonicalize(). Когда передается относительный путь, сегменты ".." в начале пути остаются:
1 2
echo Path::canonicalize('../uploads/../config/config.yaml');
// => ../config/config.yaml
Искаженые пути возвращаются неизмененными:
1 2
echo Path::canonicalize('C:Programs/PHP/php.ini');
// => C:Programs/PHP/php.ini
Преобразование абсолютных/относительных путей
Абсолютные/относительные пути могут быть преобразованы с помощью методов makeAbsolute() и makeRelative().
Метод makeAbsolute() ожидает относительный путь и базовый путь, на котором основать относительный путь:
1 2
echo Path::makeAbsolute('config/config.yaml', '/var/www/project');
// => /var/www/project/config/config.yaml
Если абсолютный путь передан в первом аргументе, абсолютный путь возвращается неизмененным:
1 2
echo Path::makeAbsolute('/usr/share/lib/config.ini', '/var/www/project');
// => /usr/share/lib/config.ini
Метод разрешает сегменты "..", если такие были:
1 2
echo Path::makeAbsolute('../config/config.yaml', '/var/www/project/uploads');
// => /var/www/project/config/config.yaml
Этот метод очень полезен, если вы хотите иметь возможность принимать относительные нути (к примеру, относительные по отношению к корневому каталогу вашего проекта) и абсолютные пути одновременно.
makeRelative() - это инверсированная операция makeAbsolute():
1 2
echo Path::makeRelative('/var/www/project/config/config.yaml', '/var/www/project');
// => config/config.yaml
Если путь не находится в базовом пути, метод добавит сегменты "..", где необходимо:
1 2
echo Path::makeRelative('/var/www/project/config/config.yaml', '/var/www/project/uploads');
// => ../config/config.yaml
Используйте makeAbsolute() и makeRelative(), чтобы проверить, является путь относительным или абсолютным:
1 2
Path::isAbsolute('C:\Programs\PHP\php.ini')
// => true
Все четыре метода внутренне каноникализируют переданный путь.
Поиск наиболее длинных базовых путей
Когда вы храните абсолютные пути файлов в файловой системе, это приводит к большому количеству дублированной информации:
1 2 3 4 5 6 7
return [
'/var/www/vhosts/project/httpdocs/config/config.yaml',
'/var/www/vhosts/project/httpdocs/config/routing.yaml',
'/var/www/vhosts/project/httpdocs/config/services.yaml',
'/var/www/vhosts/project/httpdocs/images/banana.gif',
'/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
];
Количество дублированной информации особенно заметно при хранении большого количества путей. Вы можете использовать getLongestCommonBasePath(), чтобы увидеть список путей для общего базового пути:
1 2 3 4 5 6 7 8 9 10
$paths = [
'/var/www/vhosts/project/httpdocs/config/config.yaml',
'/var/www/vhosts/project/httpdocs/config/routing.yaml',
'/var/www/vhosts/project/httpdocs/config/services.yaml',
'/var/www/vhosts/project/httpdocs/images/banana.gif',
'/var/www/vhosts/project/httpdocs/uploads/images/nicer-banana.gif',
];
Path::getLongestCommonBasePath($paths);
// => /var/www/vhosts/project/httpdocs
Используйте этот путь вместе с makeRelative(), чтобы сократить сохраненные пути:
1 2 3 4 5 6 7 8 9
$bp = '/var/www/vhosts/project/httpdocs';
return [
$bp.'/config/config.yaml',
$bp.'/config/routing.yaml',
$bp.'/config/services.yaml',
$bp.'/images/banana.gif',
$bp.'/uploads/images/nicer-banana.gif',
];
getLongestCommonBasePath() всегда возвращает каноникальные пути.
Используйте isBasePath(), чтобы протестировать, является ли путь базовым:
1 2 3 4 5 6 7 8
Path::isBasePath("/var/www", "/var/www/project");
// => true
Path::isBasePath("/var/www", "/var/www/project/..");
// => true
Path::isBasePath("/var/www", "/var/www/project/../..");
// => false
Поиск каталогов/корневых каталогов
PHP предлагает функцию dirname, чтобы получить путь каталога пути файла. Этот метод имеет несколько особенностей:
dirname()
не принимает обратные слеши на UNIXdirname("C:/Programs")
возвращает "C:", а не "C:/"dirname("C:/")
возвращает ".", а не "C:/"dirname("C:")
возвращает ".", а не "C:/"dirname("Programs")
возвращает ".", а не ""dirname()
не каноникализирует результат
getDirectory() исправляет эти недостатки:
1 2
echo Path::getDirectory("C:\Programs");
// => C:/
Кроме того, вы можете использовать getRoot(), чтобы получить корень пути:
1 2 3 4 5
echo Path::getRoot("/etc/apache2/sites-available");
// => /
echo Path::getRoot("C:\Programs\Apache\Config");
// => C:/
Обработка ошибок
Когда что-то идёт не так, вызывается исключение, реализующее ExceptionInterface или IOExceptionInterface.
Note
Если создание каталога проходит неуспешно, вызывается IOException.