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

Domain Bundle Laravel Package

open-solid/domain-bundle

A Laravel bundle for structuring domain-driven applications with SOLID-friendly building blocks, helping organize domain logic into clear, reusable components while keeping framework concerns separate from your core business model.

View on GitHub
Deep Wiki
Context7

Getting Started

Know what you're installing. open-solid/domain-bundle is distributed as a Symfony bundle, not a Laravel package. There's no extra.laravel.providers entry and no service provider auto-discovery, so composer require open-solid/domain-bundle will not wire anything into a Laravel app on its own. Decide up front which you want:

  1. The domain library code only — the DDD primitives (aggregates, domain events, value objects, repository contracts). This is the normal path in Laravel: require the package, don't register the bundle, and bind the repository interfaces yourself.
  2. Full bundle integration — only worth it if you're running Symfony alongside Laravel (e.g. a shared domain layer across two apps). You'd need to hand-write a Laravel service provider that mimics the bundle's services.yaml.

Where to look first, in this order:

  • README.md — install/registration instructions and the canonical example. If it shows bundles.php registration, that confirms the Symfony-only path.
  • composer.json — PHP constraint, symfony/* dependencies (a hard symfony/framework-bundle requirement is a strong signal the primitives aren't cleanly separable), and autoload map for the namespace you'll actually use.
  • CHANGELOG.md and the v1.0.4...v1.0.5 diff — the release notes for this version are only a compare link, so the diff is your actual changelog. git diff v1.0.4 v1.0.5 -- src/ before you bump.
  • src/ for the base classes and tests/ for real usage examples — tests are usually more current than the README.

First use case: model one aggregate with a domain event and dispatch it after the database transaction commits. Do this in a throwaway branch before committing the package to your architecture — it tells you fast whether the event/dispatch model matches Laravel's DB::afterCommit() and queue semantics, which is the single biggest integration question.

Implementation Patterns

Bind repository contracts to Eloquent implementations. The package will expose interfaces (or abstract repositories); your job is a Laravel-side implementation backed by Eloquent or Query Builder, registered in a DomainServiceProvider. Keep the mapping in one place so swapping persistence later is a container change, not a domain change.

Publish events after commit, not inside the aggregate. Collect events on the aggregate, then in your application service:

DB::transaction(function () use ($order) {
    $this->orders->save($order);
    $events = $order->releaseEvents();
});

DB::afterCommit(fn () => collect($events)->each(fn ($e) => event($e)));

This avoids dispatching events for work that gets rolled back — the most common production bug when bolting a domain-event package onto Eloquent.

Map domain events to Laravel events or jobs deliberately. Either your domain events are plain PHP objects and you translate them into Laravel events at the boundary, or you let them be dispatched directly. Translation costs a class per event but keeps the domain free of Illuminate\Contracts\Events\Dispatcher.

Structure as bounded contexts, not layers. The package's vocabulary (aggregates, repositories, domain services) maps cleanly onto app/Domain/{Context}/... with Application and Infrastructure siblings. Use the package for the Domain folder only; keep Eloquent models and HTTP concerns outside it.

Testing pattern: unit-test aggregates with in-memory repository doubles — no database, no container. Reserve integration tests for the repository implementations. This is where most of the day-to-day payoff is; if your tests still need RefreshDatabase to assert business rules, the boundary isn't being used.

Incremental adoption. Because this is a patch release (1.0.4 → 1.0.5), the public API is stable enough to pin ^1.0. Introduce it into one context, not the whole app; retrofitting aggregates onto existing Eloquent-centric models is expensive and rarely worth it mid-feature.

Gotchas and Tips

  • Bundle ≠ package. Expect DependencyInjection/, Resources/config/, and *Bundle classes. None of that is used by Laravel. Verify with composer show open-solid/domain-bundle and read the autoload psr-4 map — pull in only what that namespace exposes as framework-agnostic.
  • No changelog content for v1.0.5. The release notes are a bare compare URL. Treat it as a bugfix bump until you've read the diff; patch releases can still carry behavioural changes (exception types, null handling, event ordering). Diff src/ and the tests, then run your suite before tagging the upgrade in your app.
  • Event dispatch order and nesting. If your transaction wrapper dispatches per-event and an event handler writes to the same aggregate, you can re-enter the transaction. Collect and dispatch once, outside.
  • Queue serialisation. Domain events holding full entities won't serialise cleanly for queued listeners. Carry IDs and rehydrate in the listener.
  • Don't leak Eloquent into aggregates. Model subclasses as aggregate roots look convenient and destroy testability. Keep the aggregate a plain object with a hydrator.
  • Symfony config quirks. If you do bridge the bundle, its configuration tree (Configuration.php) won't be validated in Laravel — misconfiguration fails silently rather than at boot. Assert required bindings in your service provider's register().
  • Extension points to prefer: repository interfaces, event-collector base classes, and any provided clock/ID-generator abstractions. Override those before you consider forking; forking a low-activity domain package is a long-term maintenance cost.
  • Pin and monitor. Use "open-solid/domain-bundle": "^1.0" and watch for a 2.0 — the primitives are the kind of thing that gets renamed at a major, and those renames ripple through every aggregate you've written.
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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package