317 lines
7.7 KiB
Markdown
317 lines
7.7 KiB
Markdown
# Modular Architecture
|
|
|
|
> **🤖 AI Agents**: For EXACT file templates and copy-paste code, see [CLAUDE.md](../CLAUDE.md).
|
|
> This document explains concepts; CLAUDE.md provides strict implementation patterns.
|
|
|
|
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
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```php
|
|
// 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:
|
|
|
|
```php
|
|
// 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:
|
|
|
|
```php
|
|
// 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:
|
|
|
|
```bash
|
|
php artisan db:seed --class=PermissionSeeder
|
|
```
|
|
|
|
This registers all module permissions and assigns them to the admin role.
|
|
|
|
### Using Permissions
|
|
|
|
In Blade:
|
|
```blade
|
|
@can('stock_management.view')
|
|
<a href="{{ route('stock-management.index') }}">Stock Management</a>
|
|
@endcan
|
|
```
|
|
|
|
In Controllers:
|
|
```php
|
|
public function index()
|
|
{
|
|
$this->authorize('stock_management.view');
|
|
// ...
|
|
}
|
|
```
|
|
|
|
In Filament Resources:
|
|
```php
|
|
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:
|
|
```blade
|
|
@push('module-styles')
|
|
<link href="{{ asset('modules/stock-management/css/stock-management.css') }}" rel="stylesheet">
|
|
@endpush
|
|
```
|
|
|
|
Or inline in the view:
|
|
```blade
|
|
@push('module-styles')
|
|
<style>
|
|
.stock-table { /* ... */ }
|
|
</style>
|
|
@endpush
|
|
```
|
|
|
|
## Creating Models
|
|
|
|
### With Module Command
|
|
|
|
```bash
|
|
php artisan make:module StockManagement --model=Product
|
|
```
|
|
|
|
Creates:
|
|
- `Models/Product.php`
|
|
- Migration in `Database/Migrations/`
|
|
- Filament resource with CRUD pages
|
|
|
|
### Adding Models Later
|
|
|
|
```bash
|
|
# From project root
|
|
php artisan make:model Modules/StockManagement/Models/Inventory -m
|
|
```
|
|
|
|
Then create the Filament resource:
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
php artisan make:module StockManagement --model=Product --api
|
|
```
|
|
|
|
### 2. Edit the Migration
|
|
|
|
```php
|
|
// 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
|
|
|
|
```php
|
|
// Models/Product.php
|
|
protected $fillable = [
|
|
'name',
|
|
'sku',
|
|
'description',
|
|
'price',
|
|
'quantity',
|
|
];
|
|
|
|
protected $casts = [
|
|
'price' => 'decimal:2',
|
|
];
|
|
```
|
|
|
|
### 4. Update Filament Resource
|
|
|
|
```php
|
|
// 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
|
|
|
|
```bash
|
|
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`
|