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

Laminas Modulemanager Laravel Package

laminas/laminas-modulemanager

Laminas ModuleManager provides the infrastructure for building modular Laminas applications: it discovers and loads modules, resolves dependencies, merges configuration, and triggers lifecycle events for extensible bootstrap and application setup.

Deep Wiki
Context7

Technical Evaluation

What the package is: laminas/laminas-modulemanager is the module bootstrap layer for Laminas MVC and Mezzio. It discovers enabled modules via Composer or custom autoloaders, instantiates each Module.php, aggregates configuration from module config and *.global.php / *.local.php files into a single array, orders modules by declared dependency, and fires load/bootstrap/merge events through laminas-eventmanager. It is mature, actively released (latest 2025-10-17), BSD-3-Clause, and maintained under the Laminas project umbrella.

Architecture fit — low for a Laravel-native codebase. Laravel already implements every concern this package owns, through a different and incompatible mechanism:

Concern Laravel native laminas-modulemanager
Module discovery Composer extra.laravel.providers, package manifest Composer autoload + explicit modules list
Registration ServiceProvider::register() Module::getConfig(), onBootstrap()
Config aggregation config/*.php + mergeConfigFrom() config/autoload/*.global.php / *.local.php
Boot ordering $defer, provider dependency on bootstrap list Module::$dependencies + event priority
Lifecycle boot(), booting/booted callbacks ModuleManager events, EventManager
Container Illuminate\Container laminas-servicemanager

Introducing it into a Laravel application means running two bootstrappers, two DI containers, two event dispatchers, and two config trees in one process. That is the central architectural risk, and it is not offset by any capability Laravel lacks except declared module dependency ordering — which is better solved with nwidart/laravel-modules or a plain ordered provider list.

Where it can legitimately fit (the only cases I would fund):

  1. Strangler-fig migration from a Laminas MVC/Mezzio application to Laravel, where existing modules must remain live and bootable while Laravel takes over routes. This package is the bridge for the legacy half.
  2. Multi-framework platform shop that already publishes internal Laminas modules and wants a Laravel front end to consume the same configuration/bootstrap contracts.
  3. Selective reuse of a Laminas module's config and factories — in which case you integrate the artifacts, not the manager.

Technical risk register:

Risk Severity Note
Dual container ambiguity High Same interface bound in both containers; resolution depends on which bootstrapper won. PSR-11 makes a bridge possible, not safe.
Config divergence High Two config trees with different merge semantics and precedence; no single source of truth.
config:cache blindness High Laravel's config cache will not capture ModuleManager output; production behaviour can differ from local.
Long-running workers (Octane, Horizon) Medium-High Module merge/event side effects are per-process, not per-request; state leakage across requests.
Autoloader overlap Medium Two autoload registration paths over the same namespace roots; silent shadowing.
Performance Medium Module discovery and merge are per-boot; without an explicit merged-config cache this is a fixed startup tax.
Debuggability Medium Merge precedence is opaque; exceptions surface in Laminas' error path, not Laravel's handler.

Technical questions for engineering before any commitment:

  • Which specific Laminas modules do we need to keep bootable, and can we extract just their config and factories instead of the whole manager?
  • Is the driver a migration deadline or a genuine cross-framework product requirement?
  • What is the precedence rule when a key exists in both config/autoload/*.global.php and Laravel's config/?
  • Which container is authoritative at request time, and how do we enforce it in code review?
  • Does anything we run in production use Octane or queue workers with boot-time state?
  • Have we benchmarked nwidart/laravel-modules against the actual requirement? What is it missing?
  • Supply chain: repo metadata here is unknown/no stars — confirm Packagist ownership, GitHub provenance, and signed tags before adoption.

Recommendation: do not adopt for a greenfield Laravel service. Fund a spike only if a concrete legacy-Laminas bridging requirement exists. Opportunity score of 6.78 reads as "technically interesting, strategically narrow" — accurate.

Integration

Stack assumptions: PHP 8.1+, Laravel 10/11/12, Composer 2. The package ships no Laravel service provider; there is no package discovery, no mergeConfigFrom, no facade. All wiring is manual, which means all wiring is ours to own and test.

Candidate integration patterns, cheapest first:

  1. Config-import adapter (lowest cost, lowest risk). Boot ModuleManager once in a console command, dump the merged config array, translate it into Laravel config/ files, and consume the output as ordinary Laravel config. Keeps Laminas out of the request lifecycle entirely. Recommended default.
  2. Container bridge. Register laminas-servicemanager behind a Laravel binding of Psr\Container\ContainerInterface, with delegator factories routing service resolution back into Illuminate\Container. Feasible because both are PSR-11; costly because resolution order becomes implicit. Reserve for modules with non-trivial factories.
  3. Dual-boot kernel. ModuleManager::bootstrap() inside a Laravel service provider's register()/boot(). Only viable inside a strangler migration where Laminas still serves traffic. Highest blast radius.
  4. No integration. Depend on individual laminas-* leaf packages via Composer and skip ModuleManager. Frequently the correct answer.

Compatibility work items:

  • Pin laminas/laminas-servicemanager and laminas/laminas-eventmanager majors; they move independently of ModuleManager and of Laravel.
  • Audit Composer for autoload namespace collisions between app modules and Laminas modules; PSR-4 root overlap produces order-dependent bugs.
  • Decide PSR-14 vs Laravel's dispatcher for cross-cutting events; do not double-publish.
  • Verify no laminas-* transitive dependency conflicts with Illuminate 10/11/12 constraints (mostly clean, but check psr/container and psr/event-dispatcher version pins).
  • Confirm behaviour under php artisan config:cache and route:cache and under Octane if applicable.

Sequencing and rough sizing:

Phase Work Effort
0. Diligence Packagist/GitHub provenance, license review, security advisory history, dependency tree 1–2 days
1. Spike Boot ModuleManager standalone in a Laravel app; dump merged config; document precedence 3–5 eng days
2. Decision gate Compare against nwidart/laravel-modules and against provider-only refactor on the real requirement 1 day + review
3. Adapter build Config-import command, schema mapping, golden-file tests 5–10 eng days
4. Pilot One non-critical module through the adapter; parity tests on config output 10–15 eng days
5. Rollout Module-by-module, or bridge-container for modules that require live factories 6–10 weeks, scope-dependent

Migration direction matters: if the end state is Laravel, every integrated Laminas module is technical debt with a sunset date. Write the exit criteria into the proposal — "no Laminas modules bootable after Q3" — before writing code. If the end state is permanent coexistence, this is an architecture decision requiring sign-off beyond the team, not a package selection.

Operational

Support and lifecycle. Community-maintained under Laminas, with a healthy release cadence (latest release 2025-10-17) and security advisories published through the Laminas security process. BSD-3-Clause is permissive and commercially safe. What is not provided: a vendor SLA, an LTS commitment tied to Laravel versions, or anyone contractually accountable for a cross-framework edge case. Internal ownership must be named — a specific engineer who understands Laminas bootstrap semantics, not "the platform team."

Failure modes to instrument for:

  • Silent config overwrite. Merge precedence across module config and *.global.php/*.local.php is not obvious; a duplicate key produces a working-looking application with the wrong value. Mitigate with golden-file snapshot tests on the merged output.
  • Module ordering cycles. Declared dependencies can cycle; the failure is a bootstrap-time exception, which in a dual-boot setup may surface through the wrong error handler.
  • Missing Module.php. A module in the enabled list without a resolvable class fails late and cryptically.
  • Stale merged config in long-running processes (Octane, queue workers) — boot-time merge captured once, mutated never.
  • Autoloader shadowing where two PSR-4 roots claim the same namespace prefix, resolved by registration order.
  • Config cache poisoning in either direction: Laravel's config:cache ignoring Laminas config, or a cached merged config surviving a deploy that changed a module.

Ramp-up cost. A Laravel-standard team has no priors on EventManager, ServiceManager delegators, or Laminas module semantics. Expect 2–3 weeks before a mid-level engineer can debug a bootstrap ordering problem unaided, and a standing tax on code review: reviewers must know which container resolves a given dependency. The hiring pool for this intersection is materially smaller than for Laravel alone; treat that as a recurring cost, not a one-time one.

Operational surface to add: a command that dumps the merged config for diffing, precedence documentation in the repo, composer audit in CI, and an explicit alert if module count or bootstrap time changes unexpectedly between deploys.

Verdict for a TPM decision record: low ongoing operational burden if consumed via the config-import adapter (a build-time artifact, no request-path coupling); high and diffuse burden if ModuleManager is bootstrapped inside the Laravel request lifecycle. The cost is not the package — it is the second mental model. Adopt only against a named legacy-integration requirement with a written sunset, and default to Laravel's native provider mechanism plus Composer packages for everything else.

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.
laravel2580/idehelpers
delatbabel/viewpages
anavel/gettext
muhamadrezaar/highcharts
delatbabel/keylists
frankkessler/salesforce-laravel-oauth2-rest
anavel/foundation
wdmtech/enviricons
eii/laravel-captcha
muka/shape-reader
tdt/json
refinery29/php-cs-fixer-config
hotmeteor/eco-env
mvaliolahi/hydrate
wearede/tbcpay-php
parsnick/steak
thibaud-dauce/mattermost-php
multilinguals/apollo-client
antaresbr/collection
kr0lik/phpstan-rules