Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Path Laravel Package

lastdragon-ru/path

Laravel/PHP utilities for working with filesystem-like paths: build, normalize, join, and resolve path segments with consistent behavior across platforms. Lightweight helper functions/classes aimed at safer path manipulation in applications and libraries.

View on GitHub
Deep Wiki
Context7

Path

Provides utilities for working with file and directory paths in an object-oriented way for all path types.

Requirements

Requirement Constraint Supported by
PHP ^8.5 HEAD ⋯ 11.0.0
^8.4 HEAD ⋯ 9.2.0
^8.3 10.3.0 ⋯ 9.2.0

Installation

composer require lastdragon-ru/path

Motivation

Most similar packages consider file/directory paths as strings. It is work until we need to modify and/or actively work with them. Relative path resolution depends on the type of base path, for example:

  • /path/to/directory/file.md + ../file.txt = /path/to/file.txt
  • /path/to/directory + ../file.txt = /path/to/file.txt

The strings (in general case) don't allow us to distinguish the directory path from the file path, and so resolve the path of file.txt correctly. Strings also cannot ensure type safety - there is no way to disallow passing a directory path where only a file path is wanted, and vice versa. To solve all these problems, the package defines DirectoryPath and FilePath.

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$baseDirectory = new DirectoryPath('/path/to/directory');
$baseFile      = new FilePath('/path/to/directory/file.md');
$file          = new FilePath('../file.txt');

Example::dump((string) $baseDirectory->resolve($file));
Example::dump((string) $baseFile->resolve($file));
Example::dump((string) $baseFile->file('../../file.md'));

The (string) $baseDirectory->resolve($file) is:

"/path/to/file.txt"

The (string) $baseFile->resolve($file) is:

"/path/to/file.txt"

The (string) $baseFile->file('../../file.md') is:

"/path/file.md"

What is supported

The package works only with paths, not with URL/URI/etc, and doesn't interact with OS. The following table shows possible path types.

Type Example Root
Type::Absolute /path /
Type::Relative path, ./path, ../path ​
Type::Home ~, ~/, ~/path ~/
Type::User ~username, ~username/path ~username/
Type::Unc \\ComputerName\SharedFolder\Resource \\ComputerName\SharedFolder
Type::WindowsAbsolute C:\path C:\
Type::WindowsRelative C:path C:/<current directory>^1 or C:\^1

As a path separator, any/mix of //\ can be used, but in the normalized form all \ will always be converted into /:

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$base = new DirectoryPath('\\path\\.\\to\\directory');
$file = new FilePath('../path/../to/../file.txt');
$win  = new FilePath('c:/path/../to/../file.txt');

Example::dump((string) $base->resolve($file));
Example::dump((string) $win->normalized());

The (string) $base->resolve($file) is:

"/path/to/file.txt"

The (string) $win->normalized() is:

"C:/file.txt"

Home ~/

OS independent means that unlike e.g. \Symfony\Component\Filesystem\Path the user home directory ~/ will not be replaced to the actual path, moreover paths stated with ~/ will be treatment like absolute paths (because in almost all cases it is an absolute path).

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$home = new DirectoryPath('~/path');
$file = new FilePath('file.txt');

Example::dump($home->type);
Example::dump((string) $home->resolve($file));
Example::dump((string) $home->file('../../../file.md')); // !

The $home->type is:

LastDragon_ru\Path\Type {
  +name: "Home"
}

The (string) $home->resolve($file) is:

"~/path/file.txt"

The (string) $home->file('../../../file.md') is:

"~/file.md"

Windows

Nothing special here except how the relative path resolves^1:

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$base = new DirectoryPath('C:/path');

Example::dump(
    (string) $base->resolve(new FilePath('C:file.txt')),
);

Example::dump(
    (string) $base->resolve(new FilePath('D:file.txt')),
);

The (string) $base->resolve(new FilePath('C:file.txt')) is:

"C:/path/file.txt"

The (string) $base->resolve(new FilePath('D:file.txt')) is:

"D:/file.txt"

Universal Naming Convention (UNC)

In UNC, the root is \\server\share, so relative paths resolve based on it:

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$base = new DirectoryPath('//server/share/directory');
$file = new FilePath('../../../../../file.txt');

Example::dump((string) $base->resolve($file));

The (string) $base->resolve($file) is:

"//server/share/file.txt"

Making path relative

<?php declare(strict_types = 1);

namespace LastDragon_ru\Path\Docs\Examples;

use LastDragon_ru\LaraASP\Dev\App\Example;
use LastDragon_ru\Path\DirectoryPath;
use LastDragon_ru\Path\FilePath;

$base = new DirectoryPath('~/path/to/directory');

Example::dump((string) $base->relative(new FilePath('~/file.txt')));
Example::dump($base->relative(new FilePath('/file.txt'))); // `null`, because type differ

The (string) $base->relative(new FilePath('~/file.txt')) is:

"../../../file.txt"

The $base->relative(new FilePath('/file.txt')) is:

null

Upgrading

Please follow Upgrade Guide.

Contributing

Please use the main repository to report issues, send pull requests, or ask questions.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums