Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Package Tools Laravel Package

spatie/laravel-package-tools

A base PackageServiceProvider for Laravel package authors to quickly register and publish config, views, translations, assets, routes, migrations, commands, view components/composers, and an optional interactive install command.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require spatie/laravel-package-tools --dev
    

    Add to your composer.json under require-dev (critical for package development).

  2. First Use Case: Replace your package’s ServiceProvider with PackageServiceProvider:

    use Spatie\LaravelPackageTools\PackageServiceProvider;
    use Spatie\LaravelPackageTools\Package;
    
    class YourPackageServiceProvider extends PackageServiceProvider
    {
        public function configurePackage(Package $package): void
        {
            $package->name('your-package')
                    ->hasConfigFile()
                    ->hasViews()
                    ->hasMigration('create_your_package_table')
                    ->hasCommand(YourCommand::class);
        }
    }
    
  3. Key Files to Review:

    • config/your-package.php (auto-generated by hasConfigFile())
    • database/migrations/ (auto-published by hasMigration())
    • resources/views/vendor/your-package/ (auto-published by hasViews())

Implementation Patterns

Core Workflows

  1. Package Registration:

    • Use configurePackage() to declare package assets (config, migrations, views, commands, etc.).
    • Example:
      $package->name('your-package')
              ->hasConfigFile()
              ->hasViews()
              ->hasCommand(InstallCommand::class);
      
  2. Asset Publishing:

    • Config: Automatically published to config/ via php artisan vendor:publish --provider="YourPackageServiceProvider".
    • Views/Migrations: Publish with --tag="your-package":
      php artisan vendor:publish --tag="your-package" --provider="YourPackageServiceProvider"
      
  3. Commands:

    • Extend Spatie\LaravelPackageTools\Commands\Concerns\WithNameInput for CLI flags.
    • Register commands in configurePackage():
      $package->hasCommand(YourCommand::class);
      
  4. Testing:

    • Use Spatie\LaravelPackageTools\Tests\CreatesApplication trait for package tests:
      use Spatie\LaravelPackageTools\Tests\CreatesApplication;
      
      class YourPackageTest extends TestCase
      {
          use CreatesApplication;
      
          public function test_example()
          {
              // Test logic here
          }
      }
      
  5. Publishing Assets:

    • Override boot() to publish assets conditionally:
      public function boot()
      {
          $this->publishes([
              __DIR__.'/../config/your-package.php' => config_path('your-package.php'),
          ], 'config');
      }
      
  6. Package Discovery:

    • Use Spatie\LaravelPackageTools\Package::discoverFor() to load package config dynamically:
      $package = Package::discoverFor('your-package');
      

Gotchas and Tips

Pitfalls

  1. Asset Overwriting:

    • Publishing migrations/configs/views without --force may fail if files exist. Use:
      php artisan vendor:publish --tag="your-package" --force
      
    • Tip: Use --ansi to see diffs before overwriting.
  2. Command Registration:

    • Commands must extend Spatie\LaravelPackageTools\Commands\Concerns\WithNameInput for proper flag handling.
    • Gotcha: Forgetting this causes CLI args to break silently.
  3. Testing Quirks:

    • CreatesApplication trait resets Laravel’s service container. Avoid testing singleton bindings directly.
    • Fix: Use app()->singleton() in tests if needed.
  4. Config Caching:

    • After publishing config, clear config cache:
      php artisan config:clear
      
    • Tip: Add this to your InstallCommand for user convenience.
  5. Migration Conflicts:

    • Fixed in 1.93.1: The package now strips timestamp prefixes when checking for existing migrations, reducing false conflicts.
    • Migrations must still have unique names (e.g., create_your_package_table). Duplicate names (excluding timestamps) may now cause fewer issues.
    • Tip: Use Schema::table() for updates to avoid conflicts.
  6. Package Naming:

    • configurePackage()->name() must match your package’s namespace (e.g., YourPackage\YourPackageServiceProvideryour-package).
    • Gotcha: Mismatches break vendor:publish tags.

Debugging Tips

  1. Check Published Assets:

    • Verify paths with:
      php artisan vendor:publish --dry-run --tag="your-package"
      
  2. Command Debugging:

    • Add ->withNameInput('name') to commands for proper argument parsing:
      $package->hasCommand(YourCommand::class)->withNameInput('name');
      
  3. Config Loading:

    • Debug config loading with:
      dd(config('your-package'));
      
  4. Package Discovery:

    • List discovered packages:
      dd(Package::discovered());
      
  5. Migration Conflicts:

    • If migrations fail to publish due to naming, ensure the base name (without timestamp) is unique:
      # Example: Check for conflicts without timestamps
      ls database/migrations/ | grep "your_package"
      

Extension Points

  1. Custom Publish Tags:

    • Extend PackageServiceProvider to add custom tags:
      public function boot()
      {
          $this->publishes([
              __DIR__.'/../resources/lang/en/json.php' => resource_path('lang/en/json.php'),
          ], 'json-translations');
      }
      
  2. Dynamic Config:

    • Use Package::discoverFor() to load config dynamically in runtime:
      $config = Package::discoverFor('your-package')->getConfig();
      
  3. Conditional Publishing:

    • Override boot() to publish assets based on environment:
      public function boot()
      {
          if (app()->environment('local')) {
              $this->publishes([...], 'local-assets');
          }
      }
      
  4. Artisan Commands:

    • Add custom commands to configurePackage():
      $package->hasCommand(YourCustomCommand::class);
      
  5. Package Events:

    • Listen to PackageDiscovered events for runtime hooks:
      event(new PackageDiscovered('your-package'));
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope
anil/file-picker
broqit/fields-ai