konsulting/project-root
Resolve the correct root path when developing a Composer package or using it as a dependency. Project Root lets you target a package name and resolve paths relative to the host project, avoiding repeated “dirty” path-detection logic.
dirname(__DIR__, 4)) with a maintainable, tested solution, saving future debugging time.php artisan my-package:generate)..env overrides) from vendored packages.public/) when a package handles compilation (e.g., Tailwind, Vite).tests/Feature in the host project).database/ directory.Adopt When:
../../../, regex-based parsing, or getcwd() hacks).Look Elsewhere If:
vendor/ and has no active maintenance).laravel/package-discovery), which may obviate the need for manual root resolution in some cases.For Executives:
*"Imagine our Laravel packages—like the new [Plugin Name] or [Microservice]—rely on hardcoded paths to reference the host project’s files. For example, if [Plugin Name] needs to read the project’s .env or generate assets in public/, it’s currently using fragile logic like dirname(__DIR__, 3). This breaks when:
/app to /src).This package, ProjectRoot, solves that with a single line of code: \Konsulting\ProjectRoot::forPackage('my-package')->resolve(__DIR__). It’s:
vendor/ with zero runtime overhead.Impact:
E_USER_WARNING for missing directories.Ask: Should we adopt this for [specific initiative, e.g., the new Plugin System]? The cost is negligible; the payoff is immediate."*
For Engineers: *"Right now, every Laravel package that needs to reference the host project’s directories is reinventing the wheel for path resolution. Here’s what that looks like today:
// ❌ Fragile (breaks if project structure changes)
$projectRoot = dirname(__DIR__, 4) . '/project-root';
// ❌ Undocumented (works on my machine)
$projectRoot = getcwd();
// ❌ Hardcoded (fragile)
$projectRoot = base_path('vendor/my-package/../../..');
ProjectRoot fixes this with:
// ✅ Clean, reliable, and self-documenting
$projectRoot = \Konsulting\ProjectRoot::forPackage('my-package')->resolve(__DIR__);
For Packages:
storage/, public/, or config/ from within a vendored package..env or write to storage/logs/.For Laravel:
base_path(), storage_path(), etc., but for dependency-aware paths.config/packages/my-package.php.For Teams:
dirname() hacks.Let’s adopt this for:
database/ directory.ProjectRoot for any package needing project-relative paths.Next Steps:
composer.json:
"require": {
"konsulting/project-root": "^1.0"
}
Risk: Minimal. The package is simple, tested, and used by [X] other projects. If we hit edge cases (e.g., symlinked vendors), we can extend it or fall back to __DIR__."*
For Technical Leads: *"### Architectural Fit This package aligns with Laravel’s modular design by providing a standardized way for dependencies to resolve the host project’s root. Key benefits:
getcwd() or regex hacks.base_path(), app_path(), etc., but for dependency contexts.dirname(__DIR__, N)getcwd()base_path('vendor/...')ProjectRoot for new packages; phase out old logic in legacy code.realpath() normalize paths correctly?vendor/a/b/c?C:\project\vendor)?composer dump-autoload --optimize?| Alternative | Pros | Cons |
|---|---|---|
| Custom path logic | No dependencies | Fragile, untested, duplicated effort. |
Laravel’s Path facade |
Native integration | Not designed for dependency contexts. |
getcwd() |
Simple | Unreliable in CLI/dependency contexts. |
| ProjectRoot | Reliable, tested, reusable | Minimal maintenance risk. |
Recommendation: Adopt ProjectRoot for dependency-aware path resolution. It’s the safest, most maintainable solution for our package-heavy architecture."*
How can I help you explore Laravel packages today?