Weave 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

Meta Laravel Package

laragear/meta

Helper utilities for Laravel package developers. Simplifies service provider bootstrapping with publishable migrations, scheduled tasks, middleware declarations (groups, aliases, priority), plus optional meta-testing helpers and class discovery tools.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require laragear/meta
    

    Add to your package's composer.json under require (not require-dev).

  2. First Use Case: In your package's ServiceProvider (e.g., MyPackageServiceProvider.php), leverage the fluent helpers in the boot() method:

    use Laragear\Meta\Meta;
    
    public function boot()
    {
        $this->withPublishableMigrations(__DIR__.'/../migrations')
             ->withSchedule(fn($schedule) => $schedule->command('my-package:cleanup')->daily());
    }
    
  3. Key Entry Points:

    • Migrations: withPublishableMigrations()
    • Scheduling: withSchedule()
    • Middleware: withMiddleware()
    • Attribute Extraction: Attr::of()
    • Builder Extensions: ExtendsBuilder trait

Implementation Patterns

1. Migrations & Database

Pattern: Centralize migration publishing and registration.

// Register and publish migrations from a subdirectory
$this->withPublishableMigrations(__DIR__.'/../database/migrations');

// Later, in your tests (if using meta-testing):
$this->assertPublishMigrations();

Workflow:

  • Use withPublishableMigrations() to auto-publish and register migrations from a specified path.
  • Combine with laragear/discover to dynamically discover migrations based on naming conventions.

2. Middleware Registration

Pattern: Declarative middleware setup with priority control.

// Register middleware globally with an alias and priority
$this->withMiddleware(MyMiddleware::class)
      ->as('my.middleware')
      ->globally()
      ->first(); // Ensures it runs first in the stack

Integration Tips:

  • Use inGroup('web') to attach middleware to specific groups.
  • Chain methods for readability (e.g., ->shared()->last()).
  • Test middleware with meta-testing helpers:
    $this->assertMiddlewareRegistered(MyMiddleware::class);
    

3. Eloquent Builder Extensions

Pattern: Extend query builders in global scopes.

class ActiveScope implements Scope
{
    use ExtendsBuilder;

    public function apply(Builder $builder, Model $model)
    {
        $builder->where('active', true);
    }

    // Extend builder with custom methods
    protected static function extendWhereVerified($builder)
    {
        return $builder->where('verified_at', '>', now());
    }
}

// Usage in queries:
Model::query()->verified(); // Calls extendWhereVerified()

Workflow:

  • Prefix builder methods with extend (e.g., extendWhereX()).
  • Access the model via $builder->getModel() if needed.
  • Works seamlessly with Laravel Octane (no stale instances).

4. Attribute Extraction

Pattern: Inspect class/object attributes dynamically.

#[MyAttribute(key: 'value')]
class User {}

$value = Attr::of(User::class)->get(MyAttribute::class, 'key'); // 'value'

Use Cases:

  • Validate package configurations at runtime.
  • Generate documentation or metadata from attributes.
  • Combine with laragear/discover to scan classes for attributes:
    $classes = Discover::classes()
        ->in(__DIR__.'/../src')
        ->withAttribute(MyAttribute::class)
        ->get();
    

5. Environment Management

Pattern: Modify .env files in commands.

use Laragear\Meta\Console\Commands\WithEnvironmentFile;

class SetApiKey extends Command
{
    use WithEnvironmentFile;

    public function handle()
    {
        $this->putEnvKey('API_KEY', $this->argument('key'));
        // Automatically writes to .env
    }
}

Workflow:

  • Useful for package installation/command-line tools.
  • Avoid manual .env file handling in tests or CLI tools.

6. Testing Helpers (meta-testing)

Pattern: Assert package behavior in tests.

// In your package's tests
$this->assertPublishMigrations();
$this->assertMiddlewareRegistered(MyMiddleware::class);
$this->assertValidationPasses(['email' => '[email protected]'], 'email');

Integration:

  • Install via composer require --dev laragear/meta-testing.
  • Use assertions for migrations, middleware, validation, and more.

Gotchas and Tips

Pitfalls

  1. Middleware Priority:

    • first()/last() must be called after globally() or inGroup().
    • Example of incorrect usage:
      $this->withMiddleware(MyMiddleware::class)
           ->first() // Won't work; priority ignored
           ->globally();
      
    • Fix: Chain globally() before first()/last().
  2. Attribute Extraction:

    • Attr::of() requires reflection on the target class/object.
    • Gotcha: PHP 8.4+ may trigger deprecation warnings for dynamic properties. Use ->get() with a default value:
      Attr::of($obj)->get(MyAttribute::class, 'key', null);
      
  3. Octane Compatibility:

    • Avoid singletons holding stale app/config/request instances.
    • Tip: Use ExtendsBuilder with static properties (initialized once per scope).
  4. Migration Publishing:

    • withPublishableMigrations() overwrites existing migrations.
    • Tip: Use unique migration table names (e.g., prefix_migration_table) to avoid conflicts.

Debugging Tips

  1. Middleware Not Registering:

    • Verify the boot() method runs (check ServiceProvider registration).
    • Use php artisan route:list to confirm middleware is attached.
  2. Builder Extensions Not Working:

    • Ensure methods are prefixed with extend.
    • Check for typos in method names (case-sensitive).
  3. Attribute Extraction Failing:

    • Confirm the attribute class is imported in the target file.
    • Use Attr::of()->has(MyAttribute::class) to debug presence.

Extension Points

  1. Custom Middleware Declaration: Extend MiddlewareDeclaration to add package-specific logic:

    $declaration = $this->withMiddleware(MyMiddleware::class);
    $declaration->extend(fn($declaration) => $declaration->withProperty('custom_key', 'value'));
    
  2. Dynamic Attribute Filters: Combine Attr with Discover to build metadata systems:

    $classes = Discover::classes()
        ->withAttribute(Deprecated::class)
        ->get();
    
  3. Environment File Hooks: Extend WithEnvironmentFile to validate/modify keys:

    protected function modifyEnvKey(string $key, $value): void
    {
        if ($key === 'API_KEY') {
            $this->validateApiKey($value);
        }
    }
    

Config Quirks

  1. Publishable Migrations:

    • The package does not auto-load migrations. Ensure your ServiceProvider is registered in config/app.php under providers.
  2. Testing Helpers:

    • meta-testing assertions require the package to be published first.
    • Tip: Use Artisan::call() to publish before assertions:
      $this->artisan('vendor:publish', ['--provider' => 'MyPackageServiceProvider']);
      $this->assertPublishMigrations();
      
  3. PHP Version:

    • Test on PHP 8.3+ (some reflection features may vary).
    • For PHP 8.4+, use Attr::of()->get(..., null) to avoid warnings.
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.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support