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

Application Primitives Laravel Package

cptburke/application-primitives

Lightweight set of PHP/Laravel application primitives: small value objects, helpers, and foundational abstractions to standardize common patterns across a codebase. Intended to be reused across projects to keep core logic consistent and reduce boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require cptburke/application-primitives
    

    No publisher or service provider is required—use primitives as standalone classes.

  2. First Use Case: Command Bus Define a command:

    namespace App\Commands;
    
    use CptBurke\ApplicationPrimitives\Command;
    
    class CreateUserCommand implements Command
    {
        public function __construct(
            public string $name,
            public string $email
        ) {}
    }
    

    Create a handler:

    namespace App\Handlers;
    
    use App\Commands\CreateUserCommand;
    use CptBurke\ApplicationPrimitives\CommandHandler;
    
    class CreateUserCommandHandler implements CommandHandler
    {
        public function handle(CreateUserCommand $command): void
        {
            // Business logic here
        }
    }
    

    Dispatch via the CommandBus:

    use CptBurke\ApplicationPrimitives\CommandBus;
    
    $bus = new CommandBus();
    $bus->dispatch(new CreateUserCommand('John', 'john@example.com'));
    
  3. Key Entry Points

    • CommandBus: Dispatch commands to handlers.
    • EventBus: Publish/subscribe to events.
    • QueryBus: Execute queries (read operations).
    • Repository: Abstract data access (e.g., Eloquent, custom DB).
    • Service: Stateless business logic wrapper.

Implementation Patterns

1. Command Bus Workflow

  • Use Case: Encapsulate actions (e.g., "Create User," "Send Email").
  • Pattern:
    // Dispatch
    $bus->dispatch(new SendEmailCommand($user->email, $template));
    
    // Handle
    class SendEmailCommandHandler implements CommandHandler
    {
        public function __construct(private EmailService $emailService) {}
    
        public function handle(SendEmailCommand $command): void
        {
            $this->emailService->send($command->to, $command->template);
        }
    }
    
  • Tip: Use dependency injection (e.g., Laravel’s container) for handlers.

2. Event-Driven Architecture

  • Use Case: Decouple side effects (e.g., logging, notifications).
  • Pattern:
    // Publish
    $bus->publish(new UserCreatedEvent($user));
    
    // Subscribe
    class LogUserCreation implements EventSubscriber
    {
        public function handle(UserCreatedEvent $event): void
        {
            Log::info("User created: {$event->user->email}");
        }
    }
    
  • Tip: Register subscribers in a service provider:
    $bus->subscribe(LogUserCreation::class);
    

3. Query Bus for Read Operations

  • Use Case: Fetch data (e.g., "Get User by ID").
  • Pattern:
    $queryBus = new QueryBus();
    $user = $queryBus->ask(new GetUserQuery($userId));
    
  • Tip: Combine with DTOs for strong typing:
    class GetUserQuery implements Query
    {
        public function __construct(public int $id) {}
    }
    

4. Repository Pattern

  • Use Case: Abstract data access (e.g., Eloquent, custom DB).
  • Pattern:
    class UserRepository implements Repository
    {
        public function find(int $id): ?User
        {
            return User::find($id);
        }
    }
    
  • Tip: Use interfaces for testability:
    $repository = new UserRepository(); // Real
    $repository = $this->mock(UserRepository::class); // Test
    

5. Services for Business Logic

  • Use Case: Reusable, stateless operations (e.g., "Calculate Tax").
  • Pattern:
    class TaxCalculatorService implements Service
    {
        public function calculate(float $amount): float
        {
            return $amount * 1.1; // 10% tax
        }
    }
    
  • Tip: Inject dependencies via constructor.

6. Integration with Laravel

  • Service Provider:
    use CptBurke\ApplicationPrimitives\CommandBus;
    use CptBurke\ApplicationPrimitives\EventBus;
    
    class AppServiceProvider extends ServiceProvider
    {
        public function register()
        {
            $this->app->singleton(CommandBus::class, fn() => new CommandBus());
            $this->app->singleton(EventBus::class, fn() => new EventBus());
        }
    }
    
  • Artisan Commands:
    use CptBurke\ApplicationPrimitives\CommandBus;
    
    class SendWelcomeEmailCommand extends Command
    {
        protected $signature = 'email:welcome {userId}';
        public function handle(CommandBus $bus)
        {
            $bus->dispatch(new SendWelcomeEmailCommand($this->argument('userId')));
        }
    }
    

Gotchas and Tips

1. Handler Registration

  • Gotcha: Handlers must be manually registered with the CommandBus/EventBus.
    $bus->registerHandler(
        CreateUserCommand::class,
        CreateUserCommandHandler::class
    );
    
  • Tip: Use a service provider or DI container to auto-register:
    $bus->registerHandlersFromContainer($this->app);
    

2. Circular Dependencies

  • Gotcha: Avoid circular dependencies between commands/handlers.
    • Fix: Use interfaces and abstract classes to decouple.

3. Error Handling

  • Gotcha: Unhandled exceptions in handlers crash the bus.
    • Tip: Wrap dispatch in a try-catch:
      try {
          $bus->dispatch($command);
      } catch (Exception $e) {
          Log::error("Command failed: {$e->getMessage()}");
      }
      

4. Performance

  • Gotcha: Event subscribers run synchronously by default.
    • Tip: For async processing, integrate with Laravel Queues:
      $bus->subscribe(AsyncEventSubscriber::class);
      // AsyncEventSubscriber dispatches events to a queue.
      

5. Testing

  • Gotcha: Mocking the bus requires stubbing handlers.
    • Tip: Use partial mocks:
      $bus = $this->partialMock(CommandBus::class, ['dispatch']);
      $bus->expects($this->once())->method('dispatch');
      

6. Configuration Quirks

  • Gotcha: No built-in config file—customize via constructor:
    $bus = new CommandBus([
        'handler_namespace' => 'App\\Handlers',
    ]);
    

7. Extension Points

  • Custom Middleware: Add middleware to the bus:
    $bus->pipe(new LoggingMiddleware());
    
  • Custom Query/Command Interfaces: Extend base interfaces for domain-specific needs.

8. Debugging

  • Tip: Enable debug mode for the bus:
    $bus = new CommandBus(['debug' => true]);
    
    Logs dispatched commands/handlers to storage/logs/laravel.log.

9. Laravel Artisan Commands

  • Gotcha: Commands dispatched via Artisan don’t auto-resolve Laravel bindings.
    • Fix: Manually bind dependencies:
      $this->app->bind(EmailService::class, fn() => new MailgunService());
      

10. Thread Safety

  • Gotcha: The bus is not thread-safe by default.
    • Tip: Use a singleton or container-managed instance in multi-threaded apps.
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.
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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