internal/path
Type-safe, immutable PHP path value object. Normalizes paths, handles separators cross-platform, and supports joining segments, inspecting components (name/stem/ext/parent), absolute/relative conversion, and filesystem checks (exists, file/dir, writable).
Start by installing the package via Composer:
composer require internal/path
Then import the Internal\Path class and begin with simple path creation:
use Internal\Path;
$path = Path::create('config/app.php');
echo $path; // config/app.php (stringable)
The most immediate value is replacing brittle string concatenation and DIRECTORY_SEPARATOR logic with clean, chainable, immutable path objects. For example, building a cache path:
$cache = Path::create(storage_path('app'))->join('cache', 'views');
This avoids manual path joining pitfalls and works consistently across Windows/macOS/Linux.
Path objects in domain models, services, and API payloads without fear of side effects. Methods like join(), relative(), or parent() all return new instances.$base->join(...$segments) instead of implode(DIRECTORY_SEPARATOR, ...)—it enforces absolute/relative rules and prevents accidental cross-drive references (e.g., joining /var/www with /etc/passwd throws an exception).file_exists() and is_dir() checks with Path’s typed methods like $path->isFile(), $path->isWriteable(), or $path->exists().$config = Path::create($file);
if ($config->match('config/*.php')) { /* load it */ }
->absolute($base) to safely resolve relative paths against a known root, with built-in validation that paths remain within a safe directory (e.g., preventing ../../etc escapes in user-provided paths).match(): On Unix, *.txt does not match FILE.TXT by default—use ->match('*.txt', false) for OS-agnostic case-insensitive matching (explicit control added in v1.1.0).Path::create('.env.local')->stem() returns .env.local (no stem extraction for leading dots). For multi-dot extensions (e.g., app.config.json), extension() returns only json, not config.json.join() guardrails: Passing an absolute path as a segment to join() throws LogicException. This prevents accidental path escapes but means Path::create('/tmp')->join($userPath) fails if $userPath is absolute—validate/user-input paths before joining.absolute($base) behavior: Only allows resolution if the final path resides within or under the provided base directory. Use this to sandbox file access (e.g., only allow files under /var/www/app/uploads).C:) are correctly recognized as absolute paths.Path::create('') normalizes to . (current directory). Use ->isAbsolute() or ->isEmpty() (if available in future) to guard against accidental current-dir usage.Path is Stringable, dd($path) or dump($path) shows the normalized path string—no extra casting needed.How can I help you explore Laravel packages today?