130 lines
4.6 KiB
PHP
130 lines
4.6 KiB
PHP
### Modular Architecture Guidelines
|
|
|
|
#### Overview
|
|
|
|
This application uses a custom modular architecture to organize features into distinct, self-contained units called "Modules". Each module encapsulates a specific piece of functionality, including its own models, migrations, seeders, controllers, and more. The system is designed to automatically discover and register components from enabled modules.
|
|
|
|
The core of this system is the `App\Modules\ModuleRepository`, which is responsible for finding, loading, and managing all the modules in the application. A set of helper functions is provided for easy interaction with the module repository.
|
|
|
|
#### Core Concepts
|
|
|
|
- **Module**: A directory within `app/Modules` that represents a distinct feature.
|
|
- **`ModuleRepository`**: A singleton service (`App\Modules\ModuleRepository`) that manages all modules. Accessed via the `modular()` helper.
|
|
- **`ModuleContract`**: An interface (`App\Modules\ModuleContract`) that every module's main class must implement. It defines the basic contract for a module, such as whether it's enabled.
|
|
- **Helpers**: Global functions defined in `app/Helpers/helpers.php` to simplify interaction with the modular system.
|
|
|
|
#### Module Structure
|
|
|
|
Every module is a directory located in `app/Modules/`. For a module named `Example`, the structure would be `app/Modules/Example/`.
|
|
|
|
##### Required Structure
|
|
|
|
- `app/Modules/Example/ExampleModule.php`: This is the main class for the module. It **must** implement `App\Modules\ModuleContract`.
|
|
|
|
```php
|
|
<?php
|
|
|
|
namespace App\Modules\Example;
|
|
|
|
use App\Modules\ModuleContract;
|
|
|
|
class ExampleModule implements ModuleContract
|
|
{
|
|
/**
|
|
* Check if module is enabled
|
|
*/
|
|
public function isEnabled(): bool
|
|
{
|
|
// Return true or false based on config, env, or other logic
|
|
return true;
|
|
}
|
|
}
|
|
```
|
|
|
|
##### Automatic Discovery
|
|
|
|
The following directories and their contents are automatically discovered and registered by the system for all **enabled** modules:
|
|
|
|
- `app/Modules/Example/Database/Migrations/`: Any migration files in this directory will be automatically registered and run with `php artisan migrate`.
|
|
- `app/Modules/Example/Database/Seeders/`: Any seeder classes in this directory will be automatically run with `php artisan db:seed`.
|
|
|
|
##### Conventional Structure
|
|
|
|
While not automatically registered in the same way as migrations and seeders, it is best practice to follow standard Laravel application structure within your module:
|
|
|
|
```
|
|
app/Modules/Example/
|
|
├── Database/
|
|
│ ├── Migrations/
|
|
│ │ └── 2025_09_22_000000_create_example_table.php
|
|
│ └── Seeders/
|
|
│ └── ExampleSeeder.php
|
|
├── Http/
|
|
│ ├── Controllers/
|
|
│ └── Requests/
|
|
├── Models/
|
|
│ └── Example.php
|
|
├── Repositories/
|
|
├── Resources/
|
|
└── ExampleModule.php
|
|
```
|
|
|
|
#### Creating a New Module
|
|
|
|
1. **Create the directory**: Create a new folder for your module in `app/Modules/`. For example, `app/Modules/NewFeature`.
|
|
|
|
2. **Create the Module Class**: Inside the new directory, create the main module class. The class name should be the module name suffixed with `Module`. For `NewFeature`, it would be `NewFeatureModule.php`.
|
|
|
|
```php
|
|
// app/Modules/NewFeature/NewFeatureModule.php
|
|
<?php
|
|
|
|
namespace App\Modules\NewFeature;
|
|
|
|
use App\Modules\ModuleContract;
|
|
|
|
class NewFeatureModule implements ModuleContract
|
|
{
|
|
public function isEnabled(): bool
|
|
{
|
|
return true; // Or use config('modules.new_feature.enabled', false)
|
|
}
|
|
}
|
|
```
|
|
|
|
3. **Add Components**: Add migrations, seeders, models, controllers, etc., to your module following the structure outlined above.
|
|
|
|
4. **Enable the Module**: Ensure the `isEnabled()` method in your module class returns `true`. Only enabled modules will have their migrations and seeders registered.
|
|
|
|
#### Usage via Helpers
|
|
|
|
Use the global helper functions to interact with modules throughout the application.
|
|
|
|
- **Get the Module Repository**:
|
|
```php
|
|
$repository = modular();
|
|
```
|
|
|
|
- **Get All Enabled Modules**:
|
|
```php
|
|
$enabledModules = modules(); // Returns a Collection of BaseModule objects
|
|
|
|
foreach ($enabledModules as $module) {
|
|
echo $module->name;
|
|
}
|
|
```
|
|
|
|
- **Get a Specific Module Instance**:
|
|
```php
|
|
$invoiceModule = module('Invoice'); // Returns instance of InvoiceModule
|
|
|
|
if ($invoiceModule->isEnabled()) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
- **Get the Modules Path**:
|
|
```php
|
|
$path = modules_path('Invoice/Database'); // app/Modules/Invoice/Database
|
|
```
|