internachi/modularize
Traits for Laravel package authors to add internachi/modular support to their artisan commands. The Modularize trait resolves a --module option on any command, while ModularizeGeneratorCommand routes generated files into the module directory with correct namespacing.
Architecture fit. internachi/modularize is not a framework or a plugin — it is a two-trait adapter that adds a --module=<Name> option to existing Laravel Artisan commands. Modularize makes $this->module() return a ModuleConfig value object (name, base path, namespaces, helpers) or null; ModularizeGeneratorCommand extends that behavior to Laravel GeneratorCommand subclasses so scaffolding output lands in a module directory with the module's namespace. There is no service provider, no config file, no container bindings, and no request-path execution. Architecturally, this maps onto exactly two command archetypes — file generators and module-scoped operational commands — which is a very narrow surface area and, from a risk perspective, a very desirable one: nothing in this package runs unless a command is invoked.
Integration feasibility. The integration cost per package is one Composer dependency and one trait per command class. The real work is not adoption, it is wiring: the package supplies the --module flag and module resolution, but Laravel's GeneratorCommand still asks your class for getDefaultNamespace() and getPath(). If those hooks aren't overridden, generated files compile but carry App\... namespaces inside a module — a technically-valid, operationally-wrong outcome. Practically, a team should expect one base command class and one base generator class per package (a single design decision) rather than a per-command edit. That's a clean feasibility story, but it must be planned as a refactor, not a one-line dependency add.
Technical risk.
^1.1 and confine trait usage to base classes so a future ModuleConfig API change is a one-file shim.internachi/modular. This package does nothing on its own — module discovery, registration, and configuration all live upstream. If your host applications don't use internachi/modular, there is no use case. That means the true decision is "do we standardize on internachi/modular for modular Laravel architecture?", and modularize is a downstream consequence of that decision.^13 support, which changes the Symfony console layer. Because this package touches only the console component, that is precisely where upgrade breakage surfaces first. Console command tests must run immediately after every Laravel bump.Key questions.
internachi/modular — or are we being asked to adopt both simultaneously?require blocks (versus require-dev or internal tooling)?--module and no---module paths from day one?Stack fit. This is a package-author concern only. Applications should not list modularize as a dependency; applications depend on internachi/modular. modularize belongs in the require block of internal packages that ship console commands and want those commands to accept --module. Framing this correctly at the outset prevents an entire category of "why is this here?" questions in application composer.json audits.
Migration path. The trait must be added so that the no-flag behavior is byte-identical to current behavior. The safest, lowest-drama path:
BaseCommand and BaseGeneratorCommand abstract classes in each package, both using the traits, with a single abstract namespaceSuffix() hook.--module path only where the command has a genuine module-scoped use case — do not add module awareness speculatively.Compatibility. Two axes matter. First, Laravel version: pin internachi/modularize ^1.1 (the version that introduced ^13 support) and align it with the Laravel and Symfony console versions each package supports; older packages on older Laravel may need ^1.0, which creates a small version-skew matrix to manage. Second, internachi/modular version: the ModuleConfig shape is the contract, so that dependency must be pinned and validated in the same CI run.
Sequencing. Because the value is consistency across packages ("any module-aware command accepts --module=<Name>"), sequence matters more than speed. Recommended order: (a) confirm internachi/modular is a settled architectural decision in host apps; (b) land the base classes in one package and prove the generator namespace/path overrides work end-to-end with a real module; (c) add the dual-path test matrix (with and without --module); (d) roll the pattern to remaining packages. Do not parallelize step (b) — the namespace/path wiring is the only genuinely error-prone part, and getting it right once makes the rest mechanical.
Maintenance. The package itself is effectively static: two traits, no runtime, no configuration surface. Maintenance burden therefore sits almost entirely on the consuming package teams, who own the getDefaultNamespace()/getPath() overrides and the base classes. The upstream internachi/modular release cadence is the real signal to watch; modularize is a thin convention layer and should be updated in lockstep. Budget a recurring line item for console-layer compatibility checks on every Laravel upgrade.
Support. Internal support load is small but concentrated in one predictable area: "my generated file went to the wrong place" or "$this->module() returned null." Both trace to configuration — module registration upstream, or missing namespace/path overrides locally — not to the package. Publishing a short internal troubleshooting note (dd($this->module()) to inspect name, basePath, and namespace helpers; check module registration config if null) will absorb most of this before it reaches a ticket.
Scaling. Scales well in breadth — adding --module to a new command is a trait import, and via base classes it is zero per-command effort. It does not scale into areas it wasn't designed for: no dynamic module loading, no runtime/request-path awareness, no filesystem intelligence for non-generator commands. If a task becomes "produce a file inside a module," switch to ModularizeGeneratorCommand rather than hand-rolling paths, or the inconsistency debt compounds across packages.
Failure modes. Ranked by likelihood and impact:
--module is optional; $this->module() returns null when the flag is absent. Retrofitting an existing shipped command and forgetting the guard is the single most common crash. Guard once at the top of handle().App\... imports inside modules — silent until review or refactor.getPath() override they land outside the module.internachi/modular stalls, this package stalls with it. The small code surface means a fork or inline replacement is feasible, but that contingency should be acknowledged before adoption, not after.Ramp-up. Very low for engineers who already know Laravel's console component — the entire API is two classes, and the trait files are short enough to read in a sitting. The genuine ramp-up is conceptual, not technical: engineers must internalize that (1) this is a package-author tool, not an app feature, and (2) "automatic" placement only holds once namespace and path hooks are wired. A single internal reference implementation — one package with the base classes, one module-aware generator, one module-aware operational command, and the dual-path test — teaches the pattern completely and is worth more than any documentation. Estimated time to working reference implementation: hours, not days, provided internachi/modular is already configured in a host app.
How can I help you explore Laravel packages today?