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

Ddd Symfony Bundle Laravel Package

alexandrebulete/ddd-symfony-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel Equivalent

  1. Install Dependencies (Laravel alternatives):
    composer require spatie/laravel-package-tools laravel-queue
    npm install @tom-select/tom-select
    
  2. Define Bounded Context Structure (Laravel-style):
    app/
    ├── Domains/
    │   ├── Post/
    │   │   ├── Infrastructure/
    │   │   │   ├── Laravel/
    │   │   │   │   ├── ServiceProviders/
    │   │   │   │   │   └── PostServiceProvider.php
    │   │   │   │   ├── Routes/
    │   │   │   │   │   └── api.php
    │   │   │   │   └── Console/
    │   │   │   │       └── commands.php
    
  3. Register Contexts in AppServiceProvider:
    public function boot()
    {
        $this->registerBoundedContext('Post');
        $this->registerBoundedContext('User');
    }
    
    protected function registerBoundedContext(string $context): void
    {
        $provider = "App\\Domains\\{$context}\\Infrastructure\\Laravel\\ServiceProviders\\{$context}ServiceProvider";
        if (class_exists($provider)) {
            $this->app->register($provider);
        }
    }
    
  4. Create a Command Bus (Laravel-style):
    // app/Application/Command/CommandBus.php
    class CommandBus
    {
        public function dispatch(CommandInterface $command): void
        {
            $handler = app()->make($command::class . 'Handler');
            $handler($command);
        }
    }
    
  5. Annotate Handlers (Laravel alternative to #[AsCommandHandler]):
    use App\Application\Command\CommandHandler;
    
    #[CommandHandler]
    class CreatePostHandler
    {
        public function __invoke(CreatePostCommand $command)
        {
            // Handle command
        }
    }
    
  6. Auto-Discover Handlers (via Laravel Package Tools):
    // In your ServiceProvider
    $this->app->bind(CommandBus::class, function ($app) {
        $bus = new CommandBus();
        $bus->setHandlers($this->discoverHandlers());
        return $bus;
    });
    
    protected function discoverHandlers(): array
    {
        return collect(app()->getBindings())
            ->filter(fn ($_, $key) => str_ends_with($key, 'Handler'))
            ->mapWithKeys(fn ($handler, $key) => [
                str_replace('Handler', '', $key) => $handler
            ])
            ->toArray();
    }
    

Implementation Patterns

1. Bounded Context Isolation

Symfony Pattern (via DddKernel):

// src/Post/Infrastructure/Symfony/routes/api.yaml
app_post:
    path: /posts
    controller: App\Domains\Post\Infrastructure\Symfony\Controller\PostController::index

Laravel Equivalent:

// app/Domains/Post/Infrastructure/Laravel/Routes/api.php
Route::prefix('posts')->group(function () {
    Route::get('/', [PostController::class, 'index']);
});

Workflow:

  • Symfony: Auto-loaded by DddKernel from src/*/Infrastructure/Symfony/routes/.
  • Laravel: Manually register routes in each context’s ServiceProvider or use Laravel Package Tools for auto-discovery.

2. Command/Query Bus Integration

Symfony Pattern:

#[AsCommandHandler]
class CreatePostHandler
{
    public function __invoke(CreatePostCommand $command)
    {
        // ...
    }
}

Laravel Equivalent:

// Using Laravel Macros (PHP 8.1+)
CommandBus::macro('handle', function ($command) {
    $handler = app()->make($command::class . 'Handler');
    return $handler($command);
});

// Usage
$bus->handle(new CreatePostCommand(...));

Workflow:

  1. Define Commands/Queries:
    class CreatePostCommand implements CommandInterface
    {
        public function __construct(public string $title) {}
    }
    
  2. Register Handlers:
    • Symfony: Auto-registered via #[AsCommandHandler].
    • Laravel: Use annotations (e.g., doctrine/annotations) or macros to auto-discover handlers.
  3. Dispatch Commands:
    $bus->dispatch(new CreatePostCommand('Hello World'));
    

3. Autocomplete Field (Stimulus → Livewire)

Symfony Pattern:

$builder->add('authorId', AutocompleteType::class, [
    'remote_url' => route('admin_user_autocomplete'),
]);

Laravel Equivalent (Livewire):

use Livewire\WithFileUploads;

class PostForm extends Component
{
    public $authorId;
    public $searchQuery = '';

    public function updatedSearchQuery()
    {
        $this->authorId = null;
        $this->dispatch('search-authors', query: $this->searchQuery);
    }

    public function render()
    {
        return view('livewire.post-form', [
            'authors' => Author::where('name', 'like', "%{$this->searchQuery}%")
                ->limit(5)
                ->get()
                ->map(fn ($author) => [
                    'id' => $author->id,
                    'text' => $author->email,
                ]),
        ]);
    }
}

Blade Template:

<div>
    <input
        wire:model="searchQuery"
        wire:ignore
        x-data="{ open: false }"
        x-on:search-authors.window="open = true"
        x-on:click.away="open = false"
    >
    <div x-show="open" x-transition>
        <ul>
            @foreach($authors as $author)
                <li wire:click="authorId = {{ $author['id'] }}">{{ $author['text'] }}</li>
            @endforeach
        </ul>
    </div>
</div>

4. Messenger Middleware (Symfony → Laravel Queues)

Symfony Pattern:

# config/packages/messenger.yaml
framework:
    messenger:
        buses:
            command.bus:
                middleware:
                    - doctrine_transaction

Laravel Equivalent:

// app/Providers/EventServiceProvider.php
public function boot()
{
    Queue::before(function ($job, $data) {
        if ($job instanceof CommandJob) {
            DB::beginTransaction();
        }
    });

    Queue::after(function ($job, $data) {
        if ($job instanceof CommandJob) {
            DB::commit();
        }
    });
}

Gotchas and Tips

Symfony-Specific Pitfalls

  1. Kernel Auto-Import Limitations:

    • Gotcha: DddKernel only loads files from src/*/Infrastructure/Symfony/. Misplaced configs (e.g., in config/) are ignored.
    • Fix: Use configureContainer() to merge additional configs:
      protected function configureContainer(ContainerConfigurator $container): void
      {
          $container->import($this->getProjectDir().'/config/custom/*.yaml');
      }
      
    • Laravel Alternative: Use Laravel Package Tools to define discovery rules for contexts.
  2. Messenger Bus Separation:

    • Gotcha: The bundle assumes command.bus is for writes and query.bus for reads. Mixing them can lead to race conditions (e.g., queries in a transactional command bus).
    • Fix: Validate bus usage in handlers:
      if ($this->bus->getName() === 'command.bus' && $command instanceof QueryInterface) {
          throw new \RuntimeException('Queries must use query.bus');
      }
      
  3. Autocomplete Endpoint:

    • Gotcha: The endpoint must return { "results": [...] } with id/text fields. Deviations (e.g., nested objects) break Tom Select.
    • Fix: Normalize responses:
      return response()->json([
          'results' => $users->map(fn ($user) => [
              'id' => $user->id,
              'text' => $user->email,
          ]),
      ]);
      

Laravel-Specific Gotchas

  1. Handler Discovery:

    • Gotcha: Laravel lacks native attribute-based discovery (like Symfony’s #[AsCommandHandler]).
    • Fix: Use annotations or macros:
      // Using doctrine/annotations
      $reflection = new ReflectionClass($handler);
      $annotation = $reflection->getAnnotation(CommandHandler::class);
      if ($annotation) {
          $bus->register($annotation->command, $handler);
      }
      
  2. Query Bus Responses:

    • **Got
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