Files
bhoza-shift-manager/docs/modules.md
2026-03-09 09:18:21 +00:00

7.5 KiB

Modular Architecture

This template uses a modular architecture to organize features into self-contained modules. Each module has its own admin panel, routes, views, and permissions.

Quick Start

# Create a new module
php artisan make:module StockManagement

# Create with a model
php artisan make:module StockManagement --model=Product

# Create with API routes
php artisan make:module StockManagement --api

# Skip Filament admin
php artisan make:module StockManagement --no-filament

Module Structure

app/Modules/StockManagement/
├── Config/
│   └── stock_management.php      # Module configuration
├── Database/
│   ├── Migrations/               # Module-specific migrations
│   └── Seeders/
│       └── StockManagementPermissionSeeder.php
├── Filament/
│   └── Resources/                # Admin panel resources
│       ├── StockManagementDashboardResource.php
│       └── ProductResource.php   # If --model used
├── Http/
│   ├── Controllers/
│   │   └── StockManagementController.php
│   ├── Middleware/
│   └── Requests/
├── Models/
│   └── Product.php               # If --model used
├── Policies/
├── Services/                     # Business logic
├── Routes/
│   ├── web.php                   # Frontend routes
│   └── api.php                   # API routes (if --api)
├── Resources/
│   ├── views/
│   │   ├── index.blade.php       # Module landing page
│   │   ├── layouts/
│   │   └── filament/
│   ├── css/
│   │   └── stock-management.css  # Module-specific styles
│   └── lang/en/
├── Permissions.php               # Module permissions
└── StockManagementServiceProvider.php

How Modules Work

Auto-Loading

The ModuleServiceProvider automatically:

  • Discovers all modules in app/Modules/
  • Registers each module's service provider
  • Loads routes, views, migrations, and translations

Routes

Module routes are prefixed and named automatically:

// Routes/web.php
Route::prefix('stock-management')
    ->name('stock-management.')
    ->middleware(['web', 'auth'])
    ->group(function () {
        Route::get('/', [StockManagementController::class, 'index'])
            ->name('index');
    });

Access: http://localhost:8080/stock-management

Views

Module views use a namespace based on the module slug:

// In controller
return view('stock-management::index');

// In Blade
@include('stock-management::partials.header')

Filament Admin

Each module gets its own navigation group in the admin panel:

📦 Stock Management
   ├── Dashboard
   ├── Products
   └── Inventory

Resources are automatically discovered from Filament/Resources/.

Permissions

Defining Permissions

Each module has a Permissions.php file:

// app/Modules/StockManagement/Permissions.php
return [
    'stock_management.view' => 'View Stock Management',
    'stock_management.create' => 'Create stock records',
    'stock_management.edit' => 'Edit stock records',
    'stock_management.delete' => 'Delete stock records',
    'stock_management.export' => 'Export stock data',
];

Seeding Permissions

After creating a module, run:

php artisan db:seed --class=PermissionSeeder

This registers all module permissions and assigns them to the admin role.

Using Permissions

In Blade:

@can('stock_management.view')
    <a href="{{ route('stock-management.index') }}">Stock Management</a>
@endcan

In Controllers:

public function index()
{
    $this->authorize('stock_management.view');
    // ...
}

In Filament Resources:

public static function canAccess(): bool
{
    return auth()->user()?->can('stock_management.view') ?? false;
}

Module Assets

App-Wide CSS/JS

Use the main resources/css/app.css and resources/js/app.js for shared styles.

Module-Specific Styles

Each module has its own CSS file at Resources/css/{module-slug}.css.

Include in Blade:

@push('module-styles')
    <link href="{{ asset('modules/stock-management/css/stock-management.css') }}" rel="stylesheet">
@endpush

Or inline in the view:

@push('module-styles')
<style>
    .stock-table { /* ... */ }
</style>
@endpush

Creating Models

With Module Command

php artisan make:module StockManagement --model=Product

Creates:

  • Models/Product.php
  • Migration in Database/Migrations/
  • Filament resource with CRUD pages

Adding Models Later

# From project root
php artisan make:model Modules/StockManagement/Models/Inventory -m

Then create the Filament resource:

php artisan make:filament-resource Inventory \
    --model=App\\Modules\\StockManagement\\Models\\Inventory

Move the resource to your module's Filament/Resources/ directory.

Example: Stock Management Module

1. Create the Module

php artisan make:module StockManagement --model=Product --api

2. Edit the Migration

// Database/Migrations/xxxx_create_products_table.php
Schema::create('products', function (Blueprint $table) {
    $table->id();
    $table->string('name');
    $table->string('sku')->unique();
    $table->text('description')->nullable();
    $table->decimal('price', 10, 2);
    $table->integer('quantity')->default(0);
    $table->timestamps();
});

3. Update the Model

// Models/Product.php
protected $fillable = [
    'name',
    'sku',
    'description',
    'price',
    'quantity',
];

protected $casts = [
    'price' => 'decimal:2',
];

4. Update Filament Resource

// Filament/Resources/ProductResource.php
public static function form(Form $form): Form
{
    return $form->schema([
        Forms\Components\TextInput::make('name')->required(),
        Forms\Components\TextInput::make('sku')->required()->unique(ignoreRecord: true),
        Forms\Components\Textarea::make('description'),
        Forms\Components\TextInput::make('price')->numeric()->prefix('$'),
        Forms\Components\TextInput::make('quantity')->numeric()->default(0),
    ]);
}

5. Run Migrations & Seed

php artisan migrate
php artisan db:seed --class=PermissionSeeder

6. Access

  • Frontend: http://localhost:8080/stock-management
  • Admin: http://localhost:8080/admin → Stock Management section

Best Practices

  1. Keep modules independent - Avoid tight coupling between modules
  2. Use services - Put business logic in Services/ not controllers
  3. Define clear permissions - One permission per action
  4. Use policies - For complex authorization rules
  5. Module-specific migrations - Keep data schema with the module
  6. Test modules - Create tests in tests/Modules/ModuleName/

Troubleshooting

Module not loading

  1. Check service provider exists and is named correctly
  2. Clear cache: php artisan config:clear && php artisan cache:clear
  3. Check ModuleServiceProvider is in bootstrap/providers.php

Views not found

  1. Verify view namespace matches module slug (kebab-case)
  2. Check views are in Resources/views/

Permissions not working

  1. Run php artisan db:seed --class=PermissionSeeder
  2. Clear permission cache: php artisan permission:cache-reset
  3. Verify user has role with permissions

Filament resources not showing

  1. Check resource is in Filament/Resources/
  2. Verify canAccess() returns true for your user
  3. Clear Filament cache: php artisan filament:cache-components