spatie/laravel-package-tools
A base PackageServiceProvider for Laravel package authors. Quickly register and publish config, views, translations, assets, routes, migrations, commands, view components/composers, and install commands—all via a clean, fluent API.
Start by installing the package in your Laravel project:
composer require spatie/laravel-package-tools
For new packages, use the package-skeleton-laravel repo as a template. It's pre-configured for this package.
First use case: Register your package's core features in YourPackageServiceProvider:
use Spatie\LaravelPackageTools\PackageServiceProvider;
use Spatie\LaravelPackageTools\Package;
class YourPackageServiceProvider extends PackageServiceProvider
{
public function configurePackage(Package $package): void
{
$package
->name('your-package')
->hasConfigFile()
->hasMigrations(['create_tables'])
->hasViewComponents('prefix', AlertComponent::class);
}
}
Key files to examine first:
src/YourPackageServiceProvider.php - Main configurationconfig/your-package.php - Default config filedatabase/migrations/ - Migration stubssrc/Components/ - View componentsConfiguration Phase:
// src/YourPackageServiceProvider.php
public function configurePackage(Package $package): void
{
$package
->name('your-package')
->hasConfigFile()
->hasMigrations(['create_tables'])
->hasViewComponents('prefix', AlertComponent::class);
}
Package Registration:
// In your composer.json
{
"extra": {
"laravel": {
"providers": [
"YourPackage\\YourPackageServiceProvider"
]
}
}
}
Installation Command (optional but recommended):
// src/Commands/InstallCommand.php
use Spatie\LaravelPackageTools\Commands\InstallCommand;
class InstallCommand extends InstallCommand
{
protected function getOptions(): array
{
return [
'publish-config' => 'Publish config file',
'publish-migrations' => 'Publish migrations',
'publish-assets' => 'Publish assets',
];
}
protected function getDefaultOptions(): array
{
return [
'publish-config' => true,
'publish-migrations' => true,
'publish-assets' => true,
];
}
}
1. Config Management:
// Register multiple config files
$package->hasConfigFile(['config1', 'config2']);
// Merge config with app config
config(['your-package.key' => 'value']);
// Publish with custom tag
$package->hasConfigFile('custom-config', 'your-package-custom');
2. Migration Handling:
// Register specific migrations
$package->hasMigrations(['create_tables', 'seed_data']);
// Auto-discover migrations
$package->discoversMigrations();
// Run migrations automatically
$package->hasMigrations(['create_tables'])->runsMigrations();
3. View Components:
// Register with namespace
$package->hasViewComponents('your', AlertComponent::class);
// Share data with all views
$package->sharesDataWithAllViews('package_version', '1.0.0');
// Register view composers
$package->hasViewComposer('*', function ($view) {
$view->with('shared_data', 'value');
});
4. Asset Pipeline:
// Register assets
$package->hasAssets();
// Custom publish path
$package->hasAssets('custom-path');
// Versioned assets
$package->hasAssets('assets', 'your-package-assets-v1');
1. With Laravel Packages:
// Register package routes
$package->hasRoutes(['web', 'api']);
// Register package commands
$package->hasCommands([
YourFirstCommand::class,
YourSecondCommand::class
]);
2. With Testing:
// In your package's tests
$package->hasTestSuite('tests');
// Mock package registration
$package->mockPackage();
3. With Publishing:
// Custom publish tags
$package->hasConfigFile('config', 'your-package-config-v2');
// Grouped publishing
$package->hasGroupedPublishables([
'config' => ['config1', 'config2'],
'migrations' => ['create_tables']
]);
Path Resolution Issues:
hasAssets(), hasViews(), etc. are relative to the service provider location (src/).../ for paths outside src/ (e.g., ../config/custom.php).Migration Timing:
runsMigrations() carefully or rely on vendor:publish for migrations.Config Publishing Conflicts:
config(['your-package.key' => value]) in boot() for runtime overrides.View Component Namespace Collisions:
your-package::component).Asset Versioning:
Package Registration:
php artisan package:discover
Verify your package appears in the list.
Publishable Tags:
php artisan vendor:publish --tag=your-package-*
Check all available tags.
Configuration Loading:
php artisan config:clear
php artisan config:cache
Clear caches if config changes aren't reflected.
Service Provider Boot Order:
// In your package's service provider
public function boot()
{
\Log::info('Your package booted');
}
Check logs to verify boot order.
Dynamic Configuration:
$package->hasDynamicConfig(function () {
return [
'setting' => env('YOUR_PACKAGE_SETTING', 'default')
];
});
Conditional Features:
if (app()->environment('local')) {
$package->hasMigrations(['debug_tables']);
}
Custom Install Logic:
$package->hasInstallCommand(function (InstallCommand $command) {
$command
->publishConfigFile()
->publishMigrations()
->askToStarRepoOnGitHub()
->askToRunMigrations();
});
Package Dependencies:
$package->hasDependency('spatie/laravel-activitylog', '^3.0');
Lifecycle Hooks:
$package->onActivation(function () {
\Log::info('Package activated!');
});
$package->onDeactivation(function () {
\Log::info('Package deactivated!');
});
Custom Publishables:
$package->addPublishable(
new PublishableFile('path/to/file', 'public/path')
);
Custom Tags:
$package->addPublishableTag('custom-tag', function () {
return [
new PublishableFile('path/to/file', 'public/path')
];
});
Custom Commands:
$package->hasCommand(YourCustomCommand::class)
->withOptions([
'option1' => 'Description',
'option2' => 'Description',
]);
Custom Views:
$package->hasViews('custom-views', 'path/to/views')
->withComposers(['view-name' => ViewComposer::class]);
Custom Assets:
$package->hasAssets('custom-assets', 'path/to/assets')
->withVersion('1.2.3');
How can I help you explore Laravel packages today?