composer/installers
Custom installer paths for Composer. Maps package types (e.g., WordPress plugins/themes, Drupal, Joomla) to appropriate directories so dependencies land where your CMS expects them, with flexible installer definitions for multi-project setups.
Installation:
composer require composer/installers --dev
composer.json under require-dev (recommended for most use cases).Configure composer.json:
Add a extra key with installer-paths to define where packages should be installed:
{
"extra": {
"installer-paths": {
"public/{$name}": ["type:asset-package"],
"vendor/package/{$name}": ["type:package"],
"app/Providers/{$name}/...": ["type:laravel-provider"]
}
}
}
{$name} (package name) or {$version} (version).First Use Case:
Install a package with a custom path (e.g., spatie/laravel-permission):
composer require spatie/laravel-permission
app/Providers/LaravelPermission/... (if configured).Framework-Specific Installations:
type: keys to target Laravel-specific paths (e.g., type:laravel-provider, type:laravel-model)."extra": {
"installer-paths": {
"app/Models/{$name}/...": ["type:laravel-model"]
}
}
Asset Packages:
laravel-mix, vite) to public/:
"public/js/{$name}": ["type:asset-package"]
Vendor-Specific Directories:
vendor/package-name/:
"vendor/{$name}": ["type:package"]
Conditional Install Paths:
post-install-cmd in composer.json:
"scripts": {
"post-install-cmd": [
"@php -r \"file_exists('.env') && putenv('APP_ENV='.getenv('APP_ENV'))\""
]
},
"extra": {
"installer-paths": {
"storage/framework/{$name}": ["type:cache", "APP_ENV=local"]
}
}
Laravel Packages:
Combine with laravel/package-development for local package testing.
Example:
composer require laravel/package-development --dev
Then configure package.json to link to your local package path.
CI/CD Pipelines:
Use composer install --prefer-dist --no-dev in production to avoid dev dependencies, but ensure installers is excluded:
composer install --prefer-dist --no-dev --ignore-platform-reqs
Custom Types:
Extend the installer by defining new type: keys in a custom script or plugin.
Path Conflicts:
public/js/{$name} and public/{$name}) may cause silent failures.public/js/{$name}/dist) or debug with composer dump-autoload --verbose.Case Sensitivity:
Caching Issues:
composer clear-cache
Dev vs. Prod:
installer-paths in require-dev won’t apply to --no-dev installs. Use conditional paths or scripts to handle this.Plugin Conflicts:
composer/semver), ensure they don’t override installer behavior.composer install --verbose to see where packages are installed.composer install --dry-run to preview changes without installing.composer show --path to list installed packages and their paths.Laravel-Specific Types: Leverage built-in types like:
type:laravel-provider → app/Providers/{$name}/...type:laravel-model → app/Models/{$name}/...type:laravel-migration → database/migrations/{$name}_...Dynamic Paths:
Use placeholders like {$version} or {$name} to avoid hardcoding:
"storage/logs/{$name}-{$version}": ["type:log-package"]
Post-Install Scripts: Automate post-install tasks (e.g., publishing config) with:
"scripts": {
"post-install-cmd": [
"php artisan vendor:publish --tag=config --provider=\"Vendor\\Package\\PackageServiceProvider\""
]
}
Exclude from Git:
Add generated paths to .gitignore (e.g., vendor/package-name/).
Custom Installer Logic:
Extend the installer by creating a custom plugin or using post-install-cmd to move files post-installation. Example:
composer require monolog/monolog
Then in post-install-cmd:
"post-install-cmd": [
"@php -r \"if (file_exists('vendor/monolog/monolog')) { copy('vendor/monolog/monolog/CHANGELOG.md', 'docs/monolog-changelog.md'); }\""
]
How can I help you explore Laravel packages today?