Библиотека, которая используется для построения деревьев, рассчитана только на неизменяемые файловые структуры. То есть уже после создания ее поменять нельзя. Но можно на основе старой структуры сделать новую, в которой какие-то части будут изменены.
Неизменяемая структура выбрана для этого курса не случайно. Такую структуру легче отлаживать и меньше шансов допустить ошибки. И она позволяет максимально погрузиться в использование функций высшего порядка.
Базовые операции с узлами
Пакет php-immutable-fs-trees позволяет не только создавать, но и извлекать данные из уже созданных файлов и директорий. Функции этой библиотеки позволяют не лезть во внутреннюю структуру самого дерева:
<?php
use function Php\Immutable\Fs\Trees\trees\mkdir;
use function Php\Immutable\Fs\Trees\trees\mkfile;
use function Php\Immutable\Fs\Trees\trees\getChildren;
use function Php\Immutable\Fs\Trees\trees\getName;
use function Php\Immutable\Fs\Trees\trees\getMeta;
$tree = mkdir('/', [mkfile('hexlet.log')], ['hidden' => true]);
getName($tree); // '/'
getMeta($tree)['hidden']; // true
[$file] = getChildren($tree);
getName($file); // 'hexlet.log'
isset(getMeta($file)['unknown']); // false
// А вот так делать не надо
// У файлов нет детей
getChildren($file);
Дополнительно в пакете есть две функции для проверки типа. С их помощью можно выборочно работать с файлами и директориями:
<?php
use function Php\Immutable\Fs\Trees\trees\mkdir;
use function Php\Immutable\Fs\Trees\trees\mkfile;
use function Php\Immutable\Fs\Trees\trees\getChildren;
use function Php\Immutable\Fs\Trees\trees\getName;
use function Php\Immutable\Fs\Trees\trees\getMeta;
use function Php\Immutable\Fs\Trees\trees\isDirectory;
use function Php\Immutable\Fs\Trees\trees\isFile;
$tree = mkdir('/', [mkfile('hexlet.log')], ['hidden' => true]);
isDirectory($tree); // true
isFile($tree); // false
[$file] = getChildren($tree);
isFile($file); // true
isDirectory($file); // false
Рассмотренных операций хватит для выполнения любых преобразований над файлами и директориями. Начнем с самых простых, которые не требуют рекурсивного обхода.
Обработка
Любая обработка в неизменяемом стиле сводится к формированию новых данных на основе старых. Ниже мы реализуем некоторые варианты преобразования, раскрывающие эту идею.
Изменение имени файла
<?php
$file = mkfile('one', ['size' => 35]);
$newFile = mkfile('new name', getMeta($file));
Фактически здесь создается новый файл с метаданными старого.
Сортировка содержимого директории
<?php
// Сортировка в обратном порядке
$tree = mkdir('/', [
mkfile('one'),
mkfile('two'),
mkdir('three'),
]);
$children = getChildren($tree);
$newChildren = array_reverse($children);
$tree2 = mkdir(getName($tree), $newChildren, getMeta($tree));
// [
// 'name' => '/',
// 'type' => 'directory',
// 'meta' => [],
// 'children' => [
// ['name' => 'three', 'type' => 'directory', 'meta' => [], 'children' => []],
// ['name' => 'two', 'type' => 'file', 'meta' => []],
// ['name' => 'one', 'type' => 'file', 'meta' => []]
// ]
// ]
Обновление содержимого директории
<?php
// Приведение к нижнему регистру имен директорий и файлов
// внутри конкретной директории
$tree = mkdir('/', [
mkfile('oNe'),
mkfile('Two'),
mkdir('THREE'),
]);
$children = getChildren($tree);
$newChildren = array_map(function ($child) {
$name = getName($child);
if (isDirectory($child)) {
return mkdir(strtolower($name), getChildren($child), getMeta($child));
}
return mkfile(strtolower($name), getMeta($child));
}, $children);
$tree2 = mkdir(getName($tree), $newChildren, getMeta($tree));
// [
// 'name' => '/',
// 'type' => 'directory',
// 'meta' => [],
// 'children' => [
// ['name' => 'one', 'type' => 'file', 'meta' => []],
// ['name' => 'two', 'type' => 'file', 'meta' => []],
// ['name' => 'three', 'type' => 'directory', 'meta' => [], 'children' => []]
// ]
// ]
Удаление файлов внутри директории
<?php
$tree = mkdir('/', [
mkfile('one'),
mkfile('two'),
mkdir('three'),
]);
$children = getChildren($tree);
$newChildren = array_filter($children, fn($child) => isDirectory($child));
$tree2 = mkdir(getName($tree), $newChildren, getMeta($tree));
// [
// 'name' => '/',
// 'type' => 'directory',
// 'meta' => [],
// 'children' => [
// ['name' => 'three', 'type' => 'directory', 'meta' => [], 'children' => []]
// ]
// ]
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.