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 Toolkit Laravel Package

nyoncode/laravel-package-toolkit

Toolkit for building Laravel packages with less boilerplate: configure routes, migrations, translations, views/components, middleware, assets and commands. Includes install/about commands, publishing options, lifecycle hooks, and package-specific exception handling.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require nyoncode/laravel-package-toolkit
    
  2. Create a package service provider extending PackageServiceProvider and implementing Packable:
    use NyonCode\LaravelPackageToolkit\PackageServiceProvider;
    use NyonCode\LaravelPackageToolkit\Packager;
    
    class MyPackageServiceProvider extends PackageServiceProvider
    {
        public function configure(Packager $packager): void
        {
            $packager
                ->name('My Package')
                ->hasConfig()
                ->hasRoutes();
        }
    }
    
  3. Register the provider in config/app.php under providers.
  4. Publish assets (if needed):
    php artisan vendor:publish --provider="MyPackageServiceProvider"
    

First Use Case

Add a route and config:

$packager
    ->name('My Package')
    ->hasConfig(['config.php'])
    ->hasRoutes(['web.php']);
  • Place config.php in config/ and web.php in routes/.
  • Access config via config('my-package.key').
  • Routes will be loaded automatically.

Implementation Patterns

1. Modular Configuration

Use when() for environment-specific resources:

$packager
    ->hasRoutes()
    ->whenLocal(function ($packager) {
        $packager->hasConfig('local-config.php');
    })
    ->whenProduction(function ($packager) {
        $packager->hasConfig('production-config.php');
    });

2. Lifecycle Hooks for Side Effects

Leverage hooks for initialization logic:

$packager
    ->registeringPackage(function () {
        Log::info('Package is registering...');
    })
    ->bootedPackage(function () {
        Event::listen('my-event', MyListener::class);
    });

3. Conditional Middleware

Register middleware dynamically:

$packager
    ->whenEnvironment(['local'], function ($packager) {
        $packager->hasMiddlewareGlobals([DebugMiddleware::class]);
    });

4. View Component Integration

Register components with namespaces:

$packager->hasComponents([
    'admin' => [
        'dashboard' => DashboardComponent::class,
    ],
]);

Use in Blade:

<x-my-package::admin.dashboard />

5. Shared Data for Views

Pass data to all views:

$packager->hasViews(sharedData: [
    'version' => '1.0.0',
]);

6. Custom Install Command

Extend the InstallCommand:

use NyonCode\LaravelPackageToolkit\Commands\InstallCommand;

class MyInstallCommand extends InstallCommand
{
    protected $signature = 'my-package:install {--force}';
    protected $description = 'Install My Package';

    public function handle(): void
    {
        $this->call('vendor:publish', ['--provider' => 'MyPackageServiceProvider']);
        $this->info('Package installed!');
    }
}

Register in configure():

$packager->hasCommands([MyInstallCommand::class]);

Gotchas and Tips

Pitfalls

  1. Migration Timestamps:

    • Timeless migrations auto-generate timestamps on publish. Ensure no naming conflicts with existing migrations.
    • Fix: Use canLoadMigrations() to load unpublished migrations directly (but test thoroughly).
  2. Route Conflicts:

    • Package routes may clash with host app routes. Prefix package routes:
      Route::prefix('my-package')->group(function () {
          // Routes here
      });
      
  3. Conditional Logic Overhead:

    • Overusing when() can bloat the configure() method. Group related conditions:
      $packager->when(fn () => $this->app->environment('local'), function ($packager) {
          $packager->hasConfig('local-config.php')->hasCommands();
      });
      
  4. View Publishing:

    • Published views must match the viewsPath declared in hasViews(). Use absolute paths if needed:
      $packager->hasViews(directory: __DIR__.'/../../resources/views/my-package');
      
  5. Middleware Priority:

    • Global middleware runs last. Use hasMiddlewareGroups() for earlier execution in specific groups.

Debugging Tips

  • Check Published Files:

    php artisan vendor:publish --tag=config --provider="MyPackageServiceProvider" --force
    

    Verify files appear in config/ or resources/views/.

  • Lifecycle Hooks: Add debug logs to hooks to trace execution order:

    ->registeringPackage(function () {
        Log::debug('Registering package...');
    });
    
  • Route Debugging: Use php artisan route:list to verify package routes are loaded. Filter by namespace:

    php artisan route:list | grep "my-package"
    

Extension Points

  1. Custom Packager: Extend Packager to add methods:

    class CustomPackager extends Packager
    {
        public function hasWebhooks(): static
        {
            return $this->addResource('webhooks', WebhookService::class);
        }
    }
    
  2. Dynamic Resource Loading: Load resources based on runtime checks:

    $packager->when(fn () => file_exists($this->app->basePath('custom-file')), function ($packager) {
        $packager->hasConfig('custom-file');
    });
    
  3. Override Default Directories: Use absolute paths for non-standard layouts:

    $packager->hasViews(directory: __DIR__.'/../../custom-views');
    

Performance

  • Avoid hasCommands() in Production: Commands add overhead. Use whenProduction() to exclude them:

    $packager->whenLocal(function ($packager) {
        $packager->hasCommands();
    });
    
  • Lazy-Load Heavy Resources: Defer migrations or translations until needed:

    $packager->hasMigrations()->canLoadMigrations(false);
    

Testing

  • Mock the Packager: In tests, mock the Packager to verify configuration:

    $packager = $this->createMock(Packager::class);
    $provider = new MyPackageServiceProvider($this->app);
    $provider->configure($packager);
    $this->assertEquals('My Package', $packager->name());
    
  • Test Conditional Logic: Override environment checks:

    $this->app->shouldReceive('environment')->andReturn('local');
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky