LaravelPackages.net
Acme Inc.
Toggle sidebar
karnoweb/laravel-module-manager

A powerful module management system for Laravel with dependency resolution, tree structure, and Laravel 13 support

70
0
13.0.0
About karnoweb/laravel-module-manager

karnoweb/laravel-module-manager is a Laravel package for a powerful module management system for laravel with dependency resolution, tree structure, and laravel 13 support. It currently has 0 GitHub stars and 70 downloads on Packagist (latest version 13.0.0). Install it with composer require karnoweb/laravel-module-manager. Discover more Laravel packages by karnoweb or browse all Laravel packages to compare alternatives.

Last updated

Laravel Module Manager

A module/feature-flag system for Laravel with dependency resolution, tree structure, system (locked) modules, and Laravel 13 support.

For usage scenarios and examples in Persian (فارسی), see سناریوهای کاربردی.

Requirements

  • PHP 8.3+
  • Laravel 13.x

Installation

# Laravel 13
composer require karnoweb/laravel-module-manager:^13.0

# Laravel 10–12
composer require karnoweb/laravel-module-manager:^1.0

Publish config and migrations:

php artisan vendor:publish --tag=module-manager-config
php artisan vendor:publish --tag=module-manager-migrations
php artisan migrate

Configuration

Edit config/module-manager.php:

| Key | Description | |-----|-------------| | table_prefix | Optional prefix for tables (e.g. mm_mm_modules) | | tables.modules | Modules table name | | tables.dependencies | Dependencies table name | | migration_prefix | Prefix for published migration filenames | | cache.enabled | Enable cache for active status | | cache.ttl | Cache TTL (seconds) | | cache.prefix | Cache key prefix | | default_deactivation | cascade, restrict, or none | | events.enabled | Fire module events | | modules | Array of module definitions (see below) |

Defining modules in config

Add modules under modules so they can be synced with php artisan module:sync. You can use a nested structure with records: children inherit group and get parent set automatically.

Nested (recommended):

'modules' => [
    'products' => [
        'name' => 'Products',
        'description' => 'Product management',
        'group' => 'shop',
        'icon' => 'fa-box',
        'sort_order' => 0,
        'is_active' => false,
        'on_deactivate' => 'cascade',
        'requires' => [],
        'records' => [
            'simple_product' => [
                'name' => 'Simple Product',
                'is_active' => true,
                'requires' => ['products'],
            ],
            'variable_product' => [
                'name' => 'Variable Product',
                'requires' => ['products'],
            ],
        ],
    ],
],

Flat: same keys at top level; set group and parent on each module.

Sync from config:

php artisan module:sync

API Reference

Status checks

| Method | Description | |--------|-------------| | Module::active(string\|array $keys) | Returns true if module(s) are active | | Module::inactive(string $key) | Returns true if module is inactive | | Module::allActive(array $keys) | All given keys must be active | | Module::someActive(array $keys) | At least one key active |

Conditional execution

| Method | Description | |--------|-------------| | Module::when(string $key, Closure $active, ?Closure $inactive = null) | Run callback by status | | Module::unless(string $key, Closure $callback) | Run callback when inactive |

Activation / deactivation

| Method | Description | |--------|-------------| | Module::activate(string $key) | Activate module (throws on missing deps / conflicts) | | Module::deactivate(string $key) | Deactivate (throws for system modules or active dependents) | | Module::toggle(string $key) | Toggle active state; returns new state |

Validation

| Method | Description | |--------|-------------| | Module::canActivate(string $key) | Whether activation is allowed | | Module::canDeactivate(string $key) | Whether deactivation is allowed | | Module::whyCantActivate(string $key) | Reasons (e.g. missing_dependencies, conflicts) | | Module::whyCantDeactivate(string $key) | Reasons (e.g. system_module, active_dependents) |

Dependencies

| Method | Description | |--------|-------------| | Module::requires(string $module, string $dependency) | Add required dependency | | Module::conflicts(string $module, string $conflictsWith) | Add conflict (bidirectional) | | Module::suggests(string $module, string $suggestion) | Add suggestion | | Module::getDependencies(string $key) | Get required modules | | Module::getDependents(string $key) | Get modules that require this one |

Tree

| Method | Description | |--------|-------------| | Module::tree(?string $group = null) | Nested tree (with children) | | Module::children(string $key) | Direct children | | Module::descendants(string $key) | All descendants | | Module::ancestors(string $key) | All ancestors | | Module::siblings(string $key) | Siblings |

Metadata

| Method | Description | |--------|-------------| | Module::meta(string $key, string $metaKey, mixed $default = null) | Get metadata value | | Module::setMeta(string $key, string\|array $metaKey, mixed $value = null) | Set metadata |

Management

| Method | Description | |--------|-------------| | Module::define(string $key, string $name, array $options = []) | Create or update module | | Module::all() | All modules (ordered) | | Module::groups() | List of groups | | Module::group(string $group) | Modules in group | | Module::find(string $key) | Find by key or null | | Module::findOrFail(string $key) | Find or throw | | Module::flushCache() | Clear active-status cache |

Helpers

| Function | Description | |---------|-------------| | module(?string $key = null) | Manager instance or active($key) | | module_active(string\|array $keys) | Same as Module::active() | | module_inactive(string $key) | Same as Module::inactive() | | module_meta(string $key, string $metaKey, mixed $default = null) | Same as Module::meta() | | when_module(string $key, Closure $active, ?Closure $inactive = null) | Same as Module::when() |


Artisan commands

| Command | Description | |--------|-------------| | php artisan module:list | List modules (--group=, --active, --inactive) | | php artisan module:activate {key} | Activate a module | | php artisan module:deactivate {key} | Deactivate a module | | php artisan module:tree | Show tree (--group=, --json) | | php artisan module:sync | Sync modules from config (--force to skip confirm) |


Usage examples

Check and run code by module

use Karnoweb\LaravelModuleManager\Facades\Module;

if (Module::active('reports')) {
    return view('reports.dashboard');
}

Module::when('advanced_discount', function () {
    return redirect()->route('discounts.advanced');
}, function () {
    return redirect()->route('discounts.simple');
});

Blade

@module('reports')
    <a href="{{ route('reports.index') }}">Reports</a>
@endmodule

@moduleany(['simple_product', 'coding_product'])
    <a href="{{ route('products.index') }}">Products</a>
@endmoduleany

@modules(['products', 'discounts'])
    <p>Shop modules are active.</p>
@endmodules

Routes and middleware

Route::middleware(['module:reports'])->group(function () {
    Route::get('/reports', [ReportController::class, 'index']);
});

Route::middleware(['module:products,discounts'])->get('/shop', ...);

Define modules and dependencies in code

use Karnoweb\LaravelModuleManager\Facades\Module;

Module::define('products', 'Products', [
    'group' => 'shop',
    'icon' => 'fa-box',
    'is_active' => true,
]);

Module::define('simple_product', 'Simple Product', [
    'group' => 'shop',
    'parent' => 'products',
    'is_active' => true,
]);

Module::requires('simple_product', 'products');
Module::conflicts('legacy_cart', 'new_cart');
Module::suggests('reports', 'products');

System (locked) modules

Set is_system => true in config or when defining. System modules cannot be deactivated via Module::deactivate() or module:deactivate (throws SystemModuleException).

Module::define('core', 'Core', ['is_system' => true]);

Sync from config in app seeder

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Karnoweb\LaravelModuleManager\ModuleSeeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        (new ModuleSeeder)->run();
    }
}

Exceptions

| Exception | When | |-----------|------| | ModuleNotFoundException | Module key not found | | DependencyException | Missing deps or active dependents block action | | ConflictException | Conflicting module is active | | CircularDependencyException | Circular requires detected | | SystemModuleException | Deactivate attempted on system module |


License

MIT.

Comments