GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - php-internal/path: File path helper

BranchesTags
Open more actions menu

Latest commit

 

History

36 Commits
36 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
resources
resources
 
 
src
src
 
 
tests/Unit
tests/Unit
 
 
.editorconfig
.editorconfig
 
 
.gitattributes
.gitattributes
 
 
.gitignore
.gitignore
 
 
.php-cs-fixer.dist.php
.php-cs-fixer.dist.php
 
 
CHANGELOG.md
CHANGELOG.md
 
 
CLAUDE.md
CLAUDE.md
 
 
LICENSE.md
LICENSE.md
 
 
README.md
README.md
 
 
composer.json
composer.json
 
 
infection.json
infection.json
 
 
psalm-baseline.xml
psalm-baseline.xml
 
 
psalm.xml
psalm.xml
 
 
skills.json
skills.json
 
 
testo.php
testo.php
 
 

Repository files navigation

Path helper for PHP

Vibe Index Support


A type-safe library for working with file system paths. Handles normalization, cross-platform compatibility, and all the edge cases with slashes and separators.

Path is an immutable value object – all methods return new instances, so it's safe to use as a DTO, pass between layers, or store in your domain models without worrying about side effects.

Installation

composer require internal/path

PHP Latest Version on Packagist License Total Destroys

Usage

Creating paths

use Internal\Path;

// Create from string
$path = Path::create('/var/www/app');
$path = Path::create('src/helpers/utils.php');

Joining paths

$base = Path::create('/var/www');
$full = $base->join('app', 'src', 'Controller.php');
// Result: /var/www/app/src/Controller.php

// Works with Path objects too
$subdir = Path::create('logs');
$logFile = $base->join($subdir, 'app.log');

Working with path components

$file = Path::create('/home/user/documents/report.pdf');

$file->name();      // 'report.pdf'
$file->stem();      // 'report'
$file->extension(); // 'pdf'
$file->parent();    // Path('/home/user/documents')

Path checks

$path = Path::create('config/app.php');

$path->isAbsolute();  // false
$path->isRelative();  // true
$path->exists();      // checks if file/directory exists
$path->isFile();      // checks if it's a file
$path->isDir();       // checks if it's a directory
$path->isWriteable(); // checks if writable

Converting paths

$relative = Path::create('src/Path.php');
$absolute = $relative->absolute();
// Result: /current/working/directory/src/Path.php

// Resolve against custom directory
$absolute = $relative->absolute('/var/www/app');
// Result: /var/www/app/src/Path.php

// Use as string
echo $path; // Path implements Stringable

Computing relative paths

$path = Path::create('/var/www/app/src/Controller.php');

$path->tryRelative('/var/www/app');  // Path('src/Controller.php')
$path->tryRelative('/var/www/logs'); // Path('../app/src/Controller.php') – may traverse upwards
$path->tryRelative('/var/www/app/src/Controller.php'); // Path('.') – path equals base

// Returns null when a relative path cannot be built at all,
// e.g. for paths on different Windows drives
Path::create('D:/data/file.txt')->tryRelative('C:/Users'); // null

// A relative path is returned as is: Path carries no base of its own
Path::create('src/file.php')->tryRelative('/var/www'); // Path('src/file.php')

Containment checks

$path = Path::create('/var/www/app/src/file.php');

$path->isWithin('/var/www/app'); // true
$path->isWithin('/var/www');     // true
$path->isWithin('/var/log');     // false
$path->isWithin('/var/www-old'); // false – partial segment match doesn't count

// A path is always within itself
Path::create('/var/www')->isWithin('/var/www'); // true

// The base defaults to the current working directory,
// which makes it a convenient guard against path traversal in user input
Path::create('uploads/avatar.png')->isWithin(); // true
Path::create('../../etc/passwd')->isWithin();   // false

The check is lexical: paths are compared segment by segment without touching the filesystem. Segment comparison is case-insensitive on Windows and case-sensitive on Unix.

Pattern matching

$path = Path::create('/var/www/app/Controller.php');
$path->match('*.php');           // true
$path->match('/var/www/*/Con*'); // true

// Supports wildcards
$path->match('file?.txt');       // matches file1.txt, fileA.txt, etc.
$path->match('file[123].txt');   // matches file1.txt, file2.txt, file3.txt
$path->match('test/*/*.php');    // matches test/any/file.php

// Control case sensitivity with optional parameter
$file = Path::create('File.TXT');
$file->match('*.txt');              // OS default (case-insensitive on Windows, case-sensitive on Unix)
$file->match('*.txt', false);       // case-insensitive (matches on any OS)
$file->match('*.txt', true);        // case-sensitive (won't match - different case)
$file->match('*.TXT', true);        // case-sensitive (matches - exact case)

Edge cases and special handling

The library handles common edge cases automatically:

Hidden files and multiple extensions

// Hidden files (Unix-style)
$hidden = Path::create('.gitignore');
$hidden->stem();      // '.gitignore'
$hidden->extension(); // 'gitignore'

// Files with multiple dots
$config = Path::create('app.config.json');
$config->stem();      // 'app.config'
$config->extension(); // 'json' (only the last extension)

Windows paths

// Automatically normalizes Windows backslashes
$winPath = Path::create('C:\Users\Admin\Documents');
echo $winPath; // 'C:/Users/Admin/Documents'

// Windows drive letters are recognized as absolute
Path::create('C:/Program Files')->isAbsolute(); // true

Path normalization

// Removes redundant separators
Path::create('path//to///file.txt'); // 'path/to/file.txt'

// Resolves . and .. segments
Path::create('path/./to/../file.txt'); // 'path/file.txt'

// Empty path becomes current directory
Path::create(''); // '.'

Safety checks

// Cannot join absolute paths (prevents common mistakes)
$base = Path::create('/var/www');
$base->join('/etc/config'); // throws LogicException

// Cannot navigate above root in absolute paths
Path::create('/var/../../root'); // throws LogicException

Converting to absolute with custom base directory

// Relative base directory is converted to absolute first
$path = Path::create('lib/helper.php');
$path->absolute('project/app'); // resolves 'project/app/lib/helper.php' against current directory first

// Absolute path with matching base - validation passes
$absolutePath = Path::create('/var/www/app/src/file.php');
$absolutePath->absolute('/var/www/app'); // returns same path (validation OK)
$absolutePath->absolute('/var/www');     // returns same path (validation OK - parent directory)

// Absolute path with non-matching base - throws exception
$absolutePath = Path::create('/var/www/app/file.php');
$absolutePath->absolute('/home/user'); // throws LogicException - path doesn't start with base

About

File path helper

Resources

Readme
BSD-3-Clause license

Code of conduct

Code of conduct
Activity
Custom properties

Stars

13 stars

Watchers

0 watching

Forks

0 forks
Report repository

Releases

Sponsor this project

Packages

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.