composer/installers
Composer installers for PHP applications. Extends Composer with custom install paths for various frameworks and CMSs (e.g., WordPress, Drupal, Joomla). Automatically places packages in the right directories via installer types for plugin, theme, and module workflows.
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?