Утилитарный класс для построения и манипуляции файловыми путями.
NB: Документация сделана нейросетью, хотя код написан руками.
composer require karelwintersky/arris.entity.path
use Arris\Entity\Path;// Создать путь из строки
$path = new Path('/var/www/html');
echo $path; // /var/www/html
// Создать через фабричный метод
$path = Path::create('uploads/images');
echo $path->toString(); // uploads/images
// Соединить с подпутём.
// join() по умолчанию = каталог завершающий '/'; для файла — trailingSeparator: false
// не используйте такой способ, правильно - ниже
$full = Path::create('/var/www')->join('html/index.php', trailingSeparator: false);
echo $full; // /var/www/html/index.php
// Правильный способ для файлов
$full = Path::create('/var/www')->join('html')->joinName('index.php');
echo $full; // /var/www/html/index.phpnew Path(string|array|Path $path, ?bool $isAbsolutePath = null, ?bool $hasTrailingSeparator = null)Принимает путь в одном из трёх форматов:
// Строка
$p = new Path('/foo/bar/baz');
// Массив сегментов
$p = new Path(['foo', 'bar', 'baz']);
// Другой экземпляр Path
$copy = new Path($existingPath);Автоопределение флагов из строки:
| Входная строка | isAbsolutePath |
hasTrailingSeparator |
|---|---|---|
/foo/bar |
true |
false |
foo/bar/ |
false |
true |
/foo/bar/ |
true |
true |
foo/bar |
false/null |
false |
| `` (пустая) | true |
false (путь → /) |
/ |
true |
false |
Схлопываются:
- множественные слэши:
foo//bar///baz→foo/bar/baz - точки
.→ `` ../fooилиfoo/..→.→ ``
Path::create(string|array|Path $path, ?bool $isAbsolutePath = null, ?bool $hasTrailingSeparator = null): Path
Path::from(string|array|Path $path, ?bool $isAbsolutePath = null, ?bool $hasTrailingSeparator = null): PathЭквивалентны конструктору (и друг другу), но удобнее для цепочек вызовов:
$path = Path::create('/var/www')
->setTrailingSeparator(true);
$copy = Path::from($existingPath); // то же, что new Path($existingPath)Иммутабельность: переданный инстанс
Pathстрингифицируется без мутации исходника (черезtoString()с его текущим трейлинг-сепаратором). Это касается конструктора,create(),from()иjoin().
Экспортирует путь в строку. По умолчанию (null) уважает внутренний флаг hasTrailingSeparator:
путь-каталог выведется с завершающим разделителем. Явные true/false принудительно
добавляют/снимают разделитель в выводе (флаг инстанса не меняется):
$p = new Path('foo/bar/');
$p->toString(); // foo/bar/
$p->toString(false); // foo/bar
$p->toString(true); // foo/bar/Псевдоним toString() без аргументов. Позволяет использовать объект в строковом контексте:
echo new Path('/etc/nginx'); // /etc/nginxВозвращает новый экземпляр с добавленным сегментом. По умолчанию трактуется как
присоединение каталога: результат получает hasTrailingSeparator = true. Явный
$trailingSeparator переопределяет это поведение — например, для склейки пути к файлу.
$base = new Path('/var/www');
$dir = $base->join('html'); // /var/www/html/
$file = $base->join('html/index.php', trailingSeparator: false); // /var/www/html/index.php
$file = $base->join('html/index.php', trailingSeparator: true); // /var/www/html/index.php/
// Можно передать массив, строку или Path
$base->join(['assets', 'css']); // /var/www/assets/css/
$base->join(new Path('logs')); // /var/www/logs/Аналог join(), но принудительно устанавливает hasTrailingSeparator = false. Удобно для добавления имени файла:
$dir = new Path('/var/www/');
$file = $dir->joinName('index.php');
echo $file; // /var/www/index.phpПри создании, соединении и экспорте путь приводится к «актуальному» виду, как это делает обычная ОС:
- Сегмент
.и пустые сегменты нейтрализуются:foo/./bar→foo/bar. - Сегмент
..выталкивает предыдущий:a/b/../c→a/c. - Выше корня подняться нельзя. На корне
..для абсолютного пути отбрасывается (/foo→/), а для относительного — остаётся как ссылка на родителя (../fooостаётся../foo, какcd ..в оболочке).
Path::create('base')->join('dir')->join('..'); // base/
Path::create('/foo/bar')->join('..'); // /foo/
Path::create('foo')->join('..'); // '' (относительный корень)
new Path('a/b/../c'); // a/c
new Path('../foo'); // ../foo
new Path('/..'); // /Все методы мутируют текущий объект и возвращают $this для цепочек вызовов.
$path = new Path('foo/bar');
$path->setAbsolutePath(true);
echo $path; // /foo/bar$path = new Path('/var/www');
$path->setTrailingSeparator(true);
echo $path; // /var/www/ (флаг уважается по умолчанию)
echo $path->toString(false); // /var/wwwУстанавливает сразу несколько флагов. Поддерживает ключи isAbsolute и hasTrailingSeparator:
$path->setOptions([
'isAbsolute' => true,
'hasTrailingSeparator' => false,
]);Неизвестные ключи игнорируются. Значение
nullтакже игнорируется (ключ должен присутствовать с непустым значением).
Возвращает true, если по данному пути существует директория.
if ((new Path('/var/log'))->isDirectory()) { /* ... */ }Возвращает true, если путь указывает на существующий читаемый файл.
if ((new Path('/etc/hosts'))->isFile()) { /* ... */ }Создаёт директорию рекурсивно (аналог mkdir -p). Возвращает true при успехе или если директория уже существует.
$created = (new Path('/tmp/app/cache'))->makePath(0755);| Свойство | Тип | Описание |
|---|---|---|
$atoms |
array |
Массив сегментов пути (['var', 'www', 'html']) |
$isAbsolutePath |
?bool |
Путь начинается с / |
$hasTrailingSeparator |
?bool |
Путь заканчивается на / |
Класс работает только с файловыми путями. Легаси-поддержка URL (:// → :||-костыль)
вынесена из Path в отдельный класс Arris\Entity\Url (схема+хост — корень, join(),
нормализация ../.). Он не входит в состав пакета — используйте при необходимости
как самостоятельную заготовку.
- PHP 8.2+
- Реализует интерфейс
PathInterface - Разделитель сегментов:
ATOM_SEPARATOR = '/'— используется для разбора, склейки и экспорта
toString()по умолчанию уважает внутренний флагhasTrailingSeparator; явныеtrue/falseпринудительно добавляют/снимают разделитель в выводе — флаг инстанса не мутирует.join()по умолчанию трактует данные как каталог (hasTrailingSeparator = true); для склейки пути к файлу передавайтеtrailingSeparator: false.joinName()всегда сбрасывает флаг вfalse.- Сегмент
.(точка) нейтрализуется при нормализации и не попадает в$atoms(раньше превращался во внутренний пустой атом''). - Пустой атом (
'') в середине массива сегментов при проходе черезvalidateAtomне добавляется в$atoms. - Публичное свойство
$atomsможно мутировать напрямую — но при экспорте (toString) атомы всё равно нормализуются, так что'..'/'.'не уйдут в итоговую строку. - Пустая строка и
'/'дают абсолютный корень:isAbsolutePath = true, пустой$atoms,toString()→/.hasTrailingSeparatorпри этом сбрасывается вfalse(на пустом пути флаг не имеет смысла).
MIT