Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Манипуляции с виртуальной файловой системой PHP: Деревья

Библиотека, которая используется для построения деревьев, рассчитана только на неизменяемые файловые структуры. То есть уже после создания ее поменять нельзя. Но можно на основе старой структуры сделать новую, в которой какие-то части будут изменены.

Неизменяемая структура выбрана для этого курса не случайно. Такую структуру легче отлаживать и меньше шансов допустить ошибки. И она позволяет максимально погрузиться в использование функций высшего порядка.

Базовые операции с узлами

Пакет 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' => []]
//     ]
// ]

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
Занимайтесь созданием сайтов, веб-приложений, сервисов и их интеграцией с внутренними бизнес-системами на бекенд-языке PHP
10 месяцев
с нуля
Старт 21 ноября

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»