spatie/laravel-package-tools

repository·main·Indexed 21 days ago

https://github.com/spatie/laravel-package-tools

A toolkit for simplifying Laravel package development. It provides a fluent API via PackageServiceProvider to register and publish configurations, views, assets, migrations, routes, commands, and Inertia components. It includes features for creating custom installation commands and provides lifecycle hooks for package registration and booting.

Tokens
5.1K
Snippets
22
Records
25
Agent score
74%

What's inside laravel-package-tools

  1. Use Lifecycle Hooks

    main

    You can inject custom logic into the package lifecycle using these hooks:

    • registeringPackage: Called at the start of the register method of PackageServiceProvider.
    • packageRegistered: Called at the end of the register method of PackageServiceProvider.
    • bootingPackage: Called at the start of the boot method of PackageServiceProvider.
    • packageBooted: Called at the end of the boot method of PackageServiceProvider.
  2. Configure the default directory structure

    main

    The package expects a specific directory structure. When providing paths to package methods (except discoversMigrations()), paths are relative to your primary Service Provider's location (usually <package root>/src).

    Recommended structure:

    • <package root>/src/: PackageServiceProvider and logic
    • <package root>/src/Commands/: Callable and console commands
    • <package root>/src/Components/: Blade components
    • <package root>/src/Providers/: Additional Service Providers
    • <package root>/config/: Mergeable/publishable config files
    • <package root>/database/factories/: Database factories
    • <package root>/database/migrations/: Publishable stubs and loadable migrations
    • <package root>/resources/dist/: Publishable assets
    • <package root>/resources/js/pages/: Inertia views
    • <package root>/resources/lang/: International translations
    • <package root>/resources/views/: Blade views
    • <package root>/routes/: Route files
  3. Run Pest tests directly with exception support

    main

    The package uses a custom pre-loading mechanism to allow testing for InvalidPackage exceptions that occur during Laravel application bootup. If you run vendor/bin/pest directly instead of using the composer test command, you must use the -d auto_prepend_file PHP flag to ensure the tests/Prepend.php file is loaded. This ensures that exceptions thrown during bootup are correctly caught and rethrown within the Pest test lifecycle.

    php -d auto_prepend_file=tests/Prepend.php vendor/bin/pest
  4. Initialize your package with PackageServiceProvider

    main

    To use laravel-package-tools, your package's main Service Provider must extend Spatie\LaravelPackageTools\PackageServiceProvider. You must define the package name using the name() method within configurePackage().

    Note: If your package name starts with laravel-, the prefix is automatically omitted when generating short names for publishing files.

    use Spatie\LaravelPackageTools\PackageServiceProvider;
    use Spatie\LaravelPackageTools\Package;
    
    class YourPackageServiceProvider extends PackageServiceProvider
    {
        public function configurePackage(Package $package) : void
        {
            $package->name('your-package-name');
        }
    }
  5. Run tests with specific groups

    main

    You can run the test suite using composer test. The package supports running specific subsets of tests using the --group flag. This is useful for isolating tests related to specific features like Blade components, migrations, or routes.

    Supported groups include:

    • base
    • assets
    • blade
    • commands
    • config
    • inertia
    • migrations
    • provider
    • routes
    • shareddata
    • translations
    • viewcomposer
    • views
    • installer
    • legacy (for testing backwards compatibility)
    # Run all tests
    composer test
    
    # Run only blade-related tests
    composer test -- --group=blade
  6. Use PackageServiceProvider to register package features

    main

    To simplify the creation of Laravel packages, extend Spatie\LaravelPackageTools\PackageServiceProvider. You can then use the configurePackage method to define your package's configuration, views, assets, migrations, routes, and commands using a fluent API on a Package instance.

    This approach automatically handles the registration and makes various package files (like configs and migrations) publishable by the end-user.

    use Spatie\LaravelPackageTools\PackageServiceProvider;
    use Spatie\LaravelPackageTools\Package;
    use MyPackage\ViewComponents\Alert;
    use Spatie\LaravelPackageTools\Commands\InstallCommand;
    
    class YourPackageServiceProvider extends PackageServiceProvider
    {
        public function configurePackage(Package $package): void
        {
            $package
                ->name('your-package-name')
                ->hasConfigFile()
                ->hasViews()
                ->hasViewComponent('spatie', Alert::class)
                ->hasViewComposer('*', MyViewComposer::class)
                ->sharesDataWithAllViews('downloads', 3)
                ->hasTranslations()
                ->hasAssets()
                ->publishesServiceProvider('MyProviderName')
                ->hasRoute('web')
                ->hasMigration('create_package_tables')
                ->hasCommand(YourCoolPackageCommand::class)
                ->hasInstallCommand(function(InstallCommand $command) {
                    $command
                        ->publishConfigFile()
                        ->publishAssets()
                        ->publishMigrations()
                        ->copyAndRegisterServiceProviderInApp()
                        ->askToStarRepoOnGitHub();
                });
        }
    }
  7. Configure a package using the Package class

    main

    The Package class provides a fluent API to configure various package features such as config files, views, migrations, routes, and more. To use it, you typically instantiate it within your Service Provider and define the package's identity and base path. The class uses several traits to expose configuration methods for assets, blade components, commands, configs, inertia, migrations, routes, translations, and views.

    use Spatie\LaravelPackageTools\Package;
    
    $package = Package::make()
        ->name('spatie/laravel-example-package')
        ->setBasePath(__DIR__);
  8. Create a custom Install Command

    main

    Instead of requiring users to publish files manually, you can provide a single php artisan <package-name>:install command using hasInstallCommand(). This accepts a closure where you can chain actions like publishing config, assets, migrations, and more.

    You can also use startWith() and endWith() to execute custom logic at the beginning or end of the installation process.

    use Spatie\LaravelPackageTools\Commands\InstallCommand;
    
    $package
        ->name('your-package-name')
        ->hasConfigFile()
        ->hasMigration('create_package_tables')
        ->publishesServiceProvider('MyServiceProviderName')
        ->hasInstallCommand(function(InstallCommand $command) {
            $command
                ->startWith(function(InstallCommand $command) {
                    $command->info('Hello, and welcome to my great new package!');
                })
                ->publishConfigFile()
                ->publishAssets()
                ->publishMigrations()
                ->askToRunMigrations()
                ->copyAndRegisterServiceProviderInApp()
                ->askToStarRepoOnGitHub('your-vendor/your-repo-name')
                ->endWith(function(InstallCommand $command) {
                    $command->info('Have a great day!');
                });
        });
  9. Register and publish Blade views

    main

    Place views in <package root>/resources/views. Use hasViews() to register them. You can provide a custom namespace via hasViews('custom-namespace').

    Usage: If using default namespace, use view('your-package-name::viewName'). If using a custom namespace, use view('custom-namespace::viewName').

    Publishing: Users can publish via php artisan vendor:publish --tag=<package-name>-views. If using a custom namespace, use --tag=<custom-namespace>-views.

    // Default namespace
    $package->hasViews();
    
    // Custom namespace
    $package->hasViews('custom-view-namespace');
  10. Publish a Service Provider to the app

    main

    To copy an example Service Provider into the user's app/Providers directory, use publishesServiceProvider($name). The stub must be located at <package root>/resources/stubs/{$name}.php.stub.

    Publishing: Users can publish via php artisan vendor:publish --tag=<package-name>-provider.

    $package->publishesServiceProvider('MyServiceProviderName');
  11. Register and publish translations

    main

    Place translations in <package root>/resources/lang/<language-code>/.

    • PHP files: Use hasTranslations(). Access via trans('your-package-name::filename.key').
    • JSON files: Create <language-code>.json for string-key translations.

    Publishing: Users can publish via php artisan vendor:publish --tag=<package-name>-translations.

    $package
        ->name('your-package-name')
        ->hasTranslations();
    
    // Usage example for a file at resources/lang/en/translations.php
    trans('your-package-name::translations.translatable');