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

Architect Bundle Laravel Package

mb-x/architect-bundle

mb-x/architect-bundle is a PHP bundle focused on application architecture. It provides utilities for organizing and structuring your codebase, helping you maintain clearer separation of concerns as projects grow. Install via Composer and integrate it into your existing PHP stack.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the mismatch. mb-x/architect-bundle is a Symfony bundle — the Bundle suffix, the Flex-style install, and the "job layers" framing all point at Symfony's kernel/DI model. Laravel has no bundle registry, no CompilerPass, no config/packages/*.yaml. Running composer require mb-x/architect-bundle in a Laravel app will install files and register nothing. So the honest day-one framing for a Laravel developer is: this is a reference architecture you read and copy, not a dependency you adopt.

Concretely, in order:

  1. Read the README for the layer vocabulary it prescribes (presentation / application / domain / infrastructure, or whatever names it settles on). That vocabulary is the actual deliverable.
  2. Open the bundle's own src/ — a bundle like this is almost always its own best example. Look for the interfaces (the "ports") and the DI extension class that wires implementations to them. That wiring is the thing you'll re-express as a Laravel service provider.
  3. Ignore DependencyInjection/, Resources/config/, and anything referencing Symfony\Component\HttpKernel. Those are the parts that do not port.

Your first use case should be one feature, not a restructure. Pick a single non-trivial flow — "issue an invoice," "onboard a tenant" — and carve it into the bundle's layers inside your existing app. Something like:

app/Domain/Billing/            # no Illuminate imports allowed
app/Application/Billing/       # IssueInvoice action, DTOs
app/Infrastructure/Billing/    # EloquentInvoiceRepository
app/Http/Controllers/          # thin, delegates to the action

If that one slice feels better to test and change, expand. If it feels like ceremony, you've learned the answer cheaply.

Implementation Patterns

Translate the container, don't port it. The bundle's services.yaml binds interfaces to concrete classes. In Laravel that is one line per port in a service provider:

$this->app->bind(InvoiceRepository::class, EloquentInvoiceRepository::class);

Keep those bindings in a dedicated ArchitectureServiceProvider rather than scattering them through AppServiceProvider, so the seams stay visible.

Actions as the application layer. The layer the bundle is really selling is the one between HTTP and the database. In Laravel that maps cleanly onto single-purpose invokable classes: a controller validates via a FormRequest, hands a DTO to IssueInvoice::__invoke(), and returns a Resource. The action never sees a Request, and the domain never sees a model.

Let Eloquent live in infrastructure — or admit you didn't. This is the pragmatic fork in the road. Purist: domain entities are plain PHP, repositories hydrate them, Eloquent only appears in Infrastructure/. Pragmatic: Eloquent models are your infrastructure and the domain layer talks to repository interfaces that return them. The pragmatic version is far more survivable on a real Laravel codebase; just be explicit about which one you chose, because half-measures are where the layering rots.

Enforce the boundaries mechanically. The whole value proposition collapses the first time someone types use Illuminate\Support\Facades\DB; in a domain class. Back it with a Pest architecture test or Deptrac rule — expect('App\Domain')->not->toUse('Illuminate') — and run it in CI. Without this, the structure is a convention that decays in about six weeks.

Generate, don't hand-roll. If you like the shape, encode it in custom php artisan stub files or a small make command so every new feature starts conforming. Consistency is what makes the layering legible; bespoke folder layouts per developer defeat it.

Test at the layer you're testing. Domain and application tests run with no database and no HTTP — that's the payoff, and it's real. Keep HTTP feature tests at the controller boundary and don't let them drift inward.

Adopt incrementally, per module. Retrofitting an entire existing app into layers is a multi-month project with no shippable intermediate state. New modules get the structure; old ones migrate when they're already being touched.

Gotchas and Tips

Don't install it. Restating because it's the mistake people make: there is no Laravel integration path here, and no shim is going to appear for a package with 7 stars and 0 dependents. Treat the repo as documentation.

Vendor risk is the headline. 7 stars, 0 dependents, no ecosystem. Even if you were on Symfony, you'd be adopting a structural opinion from a package with essentially no production evidence behind it. Read it, learn from it, own the code you copy.

Symfony debugging instincts won't transfer. debug:container, debug:router, and the profiler's DI panel have no Laravel equivalent. You'll be using route:list, tinker, and a dd(app(YourContract::class)) to confirm bindings — which is fine, but budget for the friction if you're following Symfony-oriented docs.

Config has no analogue. Any bundle configuration under config/packages/ needs to become a config/architect.php plus a mergeConfigFrom call if you want it tunable. Usually you don't — hardcode the conventions and skip the config surface entirely.

Namespaces after copy-paste. The classic first error is a PSR-4 mismatch from lifting files out of src/. Regenerate the autoloader and grep for stray MbX\ArchitectBundle references before you write a line of new code.

Over-abstraction is the default failure mode. Four classes per controller action is how this pattern earns its bad reputation. Layers pay for themselves on flows with real branching, multiple entry points, or a second consumer (queue job, CLI command, API + web). A CRUD endpoint that reads one table does not need a domain entity, a repository interface, and a use case. Be willing to leave simple things simple — a codebase with honest inconsistency beats one where everything is uniformly wrapped.

The extension points are the interfaces. Whatever contracts the bundle defines are its real intellectual content. In Laravel those become your own app/Domain/*/…Repository and gateway interfaces — keep them narrow (two or three methods), because a wide port is just a leaky abstraction with extra steps.

If your team is Symfony-based, the transferable asset is the shared vocabulary — ports, adapters, use cases, layer ownership — not the code. Aligning on names across two stacks is worth more than aligning on file layout, and it costs nothing to adopt.

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.
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings