Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Modularize Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the package:
    composer require internachi/modularize
    
  2. Add the trait to a command:
    use InterNACHI\Modularize\Support\Modularize;
    
    class MyCommand extends Command {
        use Modularize;
    }
    
  3. Use the --module flag:
    php artisan my:command --module=Blog
    
  4. Access module data:
    public function handle() {
        if ($module = $this->module()) {
            $this->info("Module: {$module->name}");
            $this->info("Path: {$module->path}");
        }
    }
    

First Use Case: Module-Aware Generator

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

Key Files to Review

  • Support/Modularize.php: Core trait for basic module access.
  • Support/ModularizeGeneratorCommand.php: Generator-specific logic.
  • internachi/modular docs: Understand ModuleConfig methods (e.g., getNamespace()).

Implementation Patterns

Workflow: Adding Module Support to Existing Commands

  1. Identify command type:
    • File generators: Use ModularizeGeneratorCommand.
    • Other commands: Use Modularize.
  2. Add the trait:
    use InterNACHI\Modularize\Support\Modularize; // or ModularizeGeneratorCommand
    
  3. Override methods as needed:
    • For generators: getDefaultNamespace(), getPath().
    • For custom logic: Use $this->module() to access ModuleConfig.
  4. Test with --module flag:
    php artisan my:command --module=Admin
    

Integration with internachi/modular

  • ModuleConfig methods:
    • $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.
  • Example:
    if ($module = $this->module()) {
        $namespace = $module->getNamespace('Http/Controllers');
        $this->info("Generating in: {$namespace}");
    }
    

Common Patterns

  1. Fallback Logic:
    protected function getDefaultNamespace() {
        return $this->module()
            ? $this->module()->getNamespace('Http/Controllers')
            : 'App\Http\Controllers';
    }
    
  2. Dynamic Paths:
    protected function getPath($name) {
        return $this->module()
            ? $this->module()->path("database/migrations/{$name}")
            : database_path("migrations/{$name}");
    }
    
  3. Module Validation:
    if (!$this->module() || !$this->module()->exists()) {
        $this->error('Module not found or invalid.');
        return 1;
    }
    

Laravel Service Provider Integration

If your package includes a service provider, ensure internachi/modular is bootstrapped:

public function boot() {
    $this->app->make('internachi/modular')->boot();
}

Gotchas and Tips

Pitfalls

  1. Missing --module Flag:

    • Commands won’t fail if --module is omitted, but $this->module() returns null.
    • Fix: Always check $this->module() before use.
    if (!$module = $this->module()) {
        $this->error('Module required. Use --module=NAME.');
        return 1;
    }
    
  2. Namespace Collisions:

    • If a module’s namespace conflicts with global namespaces (e.g., App vs. Modules\App), generated files may fail to autoload.
    • Fix: Use $module->getNamespace() explicitly and validate it:
    $namespace = $module->getNamespace('Http/Controllers');
    if (str_contains($namespace, 'App')) {
        $this->error('Namespace conflict detected.');
        return 1;
    }
    
  3. Generator Path Overrides:

    • ModularizeGeneratorCommand does not override getStub() or getFileName(). Ensure these methods return module-aware values if needed.
    • Example:
    protected function getFileName() {
        return $this->module()
            ? "{$this->argument('name')}Service.php"
            : parent::getFileName();
    }
    
  4. Laravel 13+ Console Component:

    • The package assumes Symfony 7.x (Laravel 13+). If using older Laravel, expect console argument parsing issues.
    • Fix: Upgrade to Laravel 13+ or patch the trait to use Symfony\Component\Console directly.
  5. Module Not Found:

    • $this->module()->exists() may return false if the module is registered but not bootstrapped.
    • Fix: Ensure internachi/modular is bootstrapped in your app’s AppServiceProvider:
    public function boot() {
        app('internachi/modular')->boot();
    }
    

Debugging Tips

  1. Dump Module Data:
    $this->line(print_r($this->module(), true));
    
  2. Check Module Registration:
    php artisan modular:list
    
  3. Validate Paths:
    $this->info("Module path: " . $this->module()->path);
    $this->info("Generated path: " . $this->getPath($name));
    

Extension Points

  1. 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,
    
  2. 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);
        }
    }
    
  3. 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}';
    

Configuration Quirks

  1. 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.

  2. Autoloading: Generated files in modules must be autoloaded. Add to composer.json:

    "autoload": {
        "psr-4": {
            "Modules\\Blog\\": "modules/Blog/src/"
        }
    }
    
  3. Caching: Module paths/namespaces are cached by Laravel. Clear the cache if changes don’t reflect:

    php artisan cache:clear
    php artisan config:clear
    

Performance Considerations

  1. Avoid Repeated $this->module() Calls: Cache the result in the command’s __construct():
    private $module;
    
    public function __construct() {
        parent::__construct();
        $this->module = $this->module();
    }
    
  2. Lazy-Load ModuleConfig: For heavy commands, defer module loading until needed:
    public function handle() {
        if ($this->option('module')) {
            $module = $this->module();
            // Use $module...
        }
    }
    

Laravel 13+ Specifics

  1. Symfony 7.x Console: The package uses
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope