internachi/modularize
Adds InterNACHI Modular support to Laravel Artisan commands. Use the Modularize traits to add a --module option so commands and generator commands can target a specific module, placing generated files in the module directory with correct namespaces.
composer require internachi/modularize
use InterNACHI\Modularize\Support\Modularize;
class MyCommand extends Command {
use Modularize;
}
--module flag:
php artisan my:command --module=Blog
public function handle() {
if ($module = $this->module()) {
$this->info("Module: {$module->name}");
$this->info("Path: {$module->path}");
}
}
For file generators (e.g., MakeController), extend GeneratorCommand and use ModularizeGeneratorCommand:
use InterNACHI\Modularize\Support\ModularizeGeneratorCommand;
class MakeWidget extends GeneratorCommand {
use ModularizeGeneratorCommand;
protected function getDefaultNamespace() {
return $this->module()
? $this->module()->getNamespace('Http/Controllers')
: parent::getDefaultNamespace();
}
}
Run:
php artisan make:widget --module=Blog
Support/Modularize.php: Core trait for basic module access.Support/ModularizeGeneratorCommand.php: Generator-specific logic.internachi/modular docs: Understand ModuleConfig methods (e.g., getNamespace()).ModularizeGeneratorCommand.Modularize.use InterNACHI\Modularize\Support\Modularize; // or ModularizeGeneratorCommand
getDefaultNamespace(), getPath().$this->module() to access ModuleConfig.--module flag:
php artisan my:command --module=Admin
internachi/modular$module->name: Module name (e.g., Blog).$module->path: Base path (e.g., modules/Blog).$module->getNamespace(string $subpath): Full namespace (e.g., Modules\Blog\Http\Controllers).$module->exists(): Check if module exists.if ($module = $this->module()) {
$namespace = $module->getNamespace('Http/Controllers');
$this->info("Generating in: {$namespace}");
}
protected function getDefaultNamespace() {
return $this->module()
? $this->module()->getNamespace('Http/Controllers')
: 'App\Http\Controllers';
}
protected function getPath($name) {
return $this->module()
? $this->module()->path("database/migrations/{$name}")
: database_path("migrations/{$name}");
}
if (!$this->module() || !$this->module()->exists()) {
$this->error('Module not found or invalid.');
return 1;
}
If your package includes a service provider, ensure internachi/modular is bootstrapped:
public function boot() {
$this->app->make('internachi/modular')->boot();
}
Missing --module Flag:
--module is omitted, but $this->module() returns null.$this->module() before use.if (!$module = $this->module()) {
$this->error('Module required. Use --module=NAME.');
return 1;
}
Namespace Collisions:
App vs. Modules\App), generated files may fail to autoload.$module->getNamespace() explicitly and validate it:$namespace = $module->getNamespace('Http/Controllers');
if (str_contains($namespace, 'App')) {
$this->error('Namespace conflict detected.');
return 1;
}
Generator Path Overrides:
ModularizeGeneratorCommand does not override getStub() or getFileName(). Ensure these methods return module-aware values if needed.protected function getFileName() {
return $this->module()
? "{$this->argument('name')}Service.php"
: parent::getFileName();
}
Laravel 13+ Console Component:
Symfony\Component\Console directly.Module Not Found:
$this->module()->exists() may return false if the module is registered but not bootstrapped.internachi/modular is bootstrapped in your app’s AppServiceProvider:public function boot() {
app('internachi/modular')->boot();
}
$this->line(print_r($this->module(), true));
php artisan modular:list
$this->info("Module path: " . $this->module()->path);
$this->info("Generated path: " . $this->getPath($name));
Custom ModuleConfig:
Extend InterNACHI\Modular\Support\ModuleConfig to add custom methods:
namespace App\Modules;
use InterNACHI\Modular\Support\ModuleConfig;
class CustomModuleConfig extends ModuleConfig {
public function getCustomPath() {
return $this->path('custom/directory');
}
}
Register it in config/modular.php:
'config' => App\Modules\CustomModuleConfig::class,
Override Generator Behavior:
Extend ModularizeGeneratorCommand to customize file generation:
use InterNACHI\Modularize\Support\ModularizeGeneratorCommand;
class CustomMakeCommand extends GeneratorCommand {
use ModularizeGeneratorCommand {
getDefaultNamespace as traitGetDefaultNamespace;
}
protected function getDefaultNamespace() {
$namespace = $this->traitGetDefaultNamespace();
return str_replace('App', 'Modules\\' . $this->module()->name, $namespace);
}
}
Add Module-Specific Arguments:
Use Laravel’s --option syntax to add module-aware flags:
protected $signature = 'my:command
{--module= : The module name}
{--force : Force execution}';
config/modular.php:
Ensure the modules path is correctly configured. Default:
'modules' => base_path('modules'),
If using custom paths, update the config or extend ModuleConfig.
Autoloading:
Generated files in modules must be autoloaded. Add to composer.json:
"autoload": {
"psr-4": {
"Modules\\Blog\\": "modules/Blog/src/"
}
}
Caching: Module paths/namespaces are cached by Laravel. Clear the cache if changes don’t reflect:
php artisan cache:clear
php artisan config:clear
$this->module() Calls:
Cache the result in the command’s __construct():
private $module;
public function __construct() {
parent::__construct();
$this->module = $this->module();
}
public function handle() {
if ($this->option('module')) {
$module = $this->module();
// Use $module...
}
}
How can I help you explore Laravel packages today?