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

Module Manager Laravel Package

nasirkhan/module-manager

Powerful module management for Laravel Starter: track versions, manage migrations, resolve dependencies, and run the full module lifecycle with artisan commands like status, enable, disable, publish, and build.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require nasirkhan/module-manager. Requirements are strict: PHP ^8.3, Laravel ^12 or ^13. This is a Laravel Starter companion package, not a generic module system — if you're on stock Laravel plus nwidart/laravel-modules, expect to adapt rather than drop in.
  • Look here first, in order:
    1. php artisan module:help — the package's own command reference and workflows.
    2. php artisan module:status — enabled/disabled modules, versions, and dependency state. This is your map of the system.
    3. php artisan module:dependencies — what's unsatisfied before you enable anything.
  • Then get the app running: php artisan migrate (package modules ship migrations), and php artisan vendor:publish --tag=post-views etc. only for the module you intend to touch.
  • First real use case: customize one shipped module. Publish just that module (module:publish Post), then composer dump-autoload && php artisan config:clear, and confirm with module:status Post and module:diff Post. Publishing rewrites namespaces from Nasirkhan\ModuleManager\Modules\Post\... to Modules\Post\..., so you now own that code.

Implementation Patterns

Consume-in-vendor vs. publish-and-own. Keep package modules vendored while you're not changing them; publish only the ones you fork. Once published, package updates no longer reach that module — module:diff {module} --detailed becomes your upgrade check, and re-running vendor:publish --tag=post-migrations is a manual reconciliation step, not a merge.

Scaffolding your own modules. module:build Invoice generates the standard tree (Config/, database/migrations, Http/, routes/, Tests/, ...). Fill in module.json deliberately:

{
  "name": "Invoice",
  "alias": "invoice",
  "version": "1.0.0",
  "priority": 0,
  "requires": ["Category", "Tag"]
}

Use priority as a load-order contract in a starter app: core/auth/permission modules at 10, shared UI/menu at 5, content modules at 0. requires gives you dependency gating for free in module:status/module:dependencies.

Upgrade workflow for shipped modules — treat this as a fixed ritual after every composer update:

php artisan module:detect-updates      # what changed
php artisan module:check-migrations    # unpublished/pending migrations
php artisan vendor:publish --tag=post-migrations
php artisan migrate

Use module:track-migrations --force to re-baseline after you've confirmed and applied what's pending — it records current state as the new baseline.

Gate your own bootstrapping on module state. Wrap module-dependent registration instead of assuming presence:

use Nasirkhan\ModuleManager\Services\ModuleVersion;

$modules = app(ModuleVersion::class);

if ($modules->dependenciesSatisfied('Invoice')) {
    // register event listeners, routes, policies
}

foreach ($modules->getModulesByPriority() as $module) {
    // build a nav/menu or admin dashboard listing
}

Custom tooling on top of the services. ModuleVersion (getVersion, getDependencies, dependenciesSatisfied, getModulesByPriority) and MigrationTracker (trackModuleMigrations, getNewMigrationsSinceLastCheck, getPendingMigrations, hasUpdates) are the stable programmatic surface — good candidates to wrap in your own deploy or module:audit command rather than parsing CLI output.

Testing per module. module:make-test Post PostPublishesTest [--unit] drops into the module's Tests/Feature or Tests/Unit. Keep module tests inside the module so they travel with it when published/removed.

Feature toggling in environments. module:enable/module:disable is a cheap way to keep a module's code deployed while removing its routes/views/providers in a given environment — remember its tables and data persist either way.

Gotchas and Tips

  • The number one "it's broken" cause is autoload. After module:publish, any namespace rewrite, or adding a module: composer dump-autoload, php artisan cache:clear, php artisan config:clear. Skipping this makes modules silently absent from module:status.
  • module.json is the source of truth for version and dependency metadata. If you edit a published module, bump version there — otherwise module:diff, module:detect-updates, and the migration baseline lie to you.
  • module:track-migrations --force overwrites the baseline. It can mask genuinely pending migrations. Always run module:check-migrations / detect-updates before forcing a re-track.
  • Names in requires are matched, so casing matters ("Post", not "post" — the alias is a separate field). Watch for accidental cycles; a requires loop will make priority ordering meaningless.
  • Priority is inverted from intuition: higher values load first. Getting this backwards produces "class not found" or permission-middleware-runs-after-route errors that look unrelated.
  • Transitive dependency surprises. v7.0.0 added spatie/laravel-activitylog ^5 and intervention/image-laravel ^4 as direct deps (used by the Post model and the Jodit image connector). You may remove your own duplicates, but if your app pins different majors you'll get a conflict — check composer why before upgrading.
  • Publishing is one-way. module:remove deletes the module directory outright, and a published module isn't recoverable from vendor/ without re-publishing and re-applying your edits. Commit before publishing, removing, or --force-tracking anything.
  • The dependency surface is coupled to Laravel Starter (Menus, permissions, Livewire views, its stubs). If your app diverges from starter conventions, module:build output will need hand-editing, and the shipped modules may assume auth/menu scaffolding you don't have.
  • Debugging divergence: module:dist {module} --detailed shows exactly how your published copy drifted from the package — that's your merge brief after composer update, not a raw git diff of vendor/.
  • Extension points are thin by design: vendor publish tags per module ({alias}-migrations, -views, -config, -lang), module.json fields, and the two services. There's no documented event/hook system, so prefer wrapping the services in your own commands over patching vendor files.
  • Maturity warning: 10 stars, 0 dependents, and a history of breaking majors (v2, v7) with pre-6.9.0 changes documented only in git history. Pin an exact version, read UPGRADE.md/CHANGELOG.md on every bump, and keep a fresh module:diff/migration baseline before and after upgrading.
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel