Компонент Filesystem

Дата оновлення перекладу 2022-12-12

Компонент 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\Filesystem;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
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

Ця функція ігнорує вже існуючі каталоги.

Note

Поточний umask впливає на дозволи каталогу. Встановіть umask для вашого веб-сервера, використайте функцію PHP umask або використайте функцію chmod після створення каталогу.

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() створює символьне посилання від цілі до напрямку. Якщо файлова система не підтримує символьні поислання, доступний третій булевий аргумент:

1
2
3
4
5
// створює символьне посилання
$fileSystem->symlink('/path/to/source', '/path/to/destination');
// дублює каталог джерела, якщо файлова система не
// підтримує символьні посилання
$fileSystem->symlink('/path/to/source', '/path/to/destination', true);

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);

Якщо або файл, або каталог, що його містить, не існує, то цей метод створює їх перед додаванням змісту.

Утиліти для маніпуляцій зі шляхами

Робота зі шляхами файлів зазвичай викликає деякі труднощі:

  • Різниця платформ: шляхі файлів виглядають по-різному на різних платфоромах. Шляхи файлів 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()` не приймає зворотні слеші на UNIX
  • `dirname("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.