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 package commands via traits. Provides a --module option for console and generator commands, returning module config and generating files into the module directory with correct paths and namespaces.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package
    composer require internachi/modularize
    
  2. Add the Trait to a Command For standard commands:
    use Illuminate\Console\Command;
    use InterNACHI\Modularize\Support\Modularize;
    
    class MyCommand extends Command
    {
        use Modularize;
    
        public function handle()
        {
            if ($module = $this->module()) {
                // Module logic here
            }
        }
    }
    
  3. Use the --module Flag
    php artisan my:command --module=Blog
    

First Use Case

Make a Module-Aware Generator

use Illuminate\Console\GeneratorCommand;
use InterNACHI\Modularize\Support\ModularizeGeneratorCommand;

class MakeWidget extends GeneratorCommand
{
    use ModularizeGeneratorCommand;

    protected function getStub()
    {
        return __DIR__.'/stubs/widget.stub';
    }

    protected function getDefaultNamespace($rootNamespace = null)
    {
        return $this->module()
            ? $this->module()->getNamespace('Http/Controllers')
            : parent::getDefaultNamespace($rootNamespace);
    }
}

Run:

php artisan make:widget --module=Blog

Result: Generates modules/Blog/Http/Controllers/WidgetController.php.


Implementation Patterns

Core Workflows

  1. Module Detection in Commands

    if ($module = $this->module()) {
        $moduleName = $module->name;
        $modulePath = $module->path;
        $moduleNamespace = $module->getNamespace('App');
    }
    
    • Use Case: Dynamically adjust command behavior based on the active module.
  2. Generator Command Integration

    use ModularizeGeneratorCommand;
    
    protected function getFileName()
    {
        return $this->module()
            ? $this->module()->name.'/'.$this->argument('name')
            : parent::getFileName();
    }
    
    • Use Case: Ensure generated files are placed in the correct module directory.
  3. Fallback Logic for Non-Module Commands

    protected function getDefaultNamespace($rootNamespace = null)
    {
        return $this->module()
            ? $this->module()->getNamespace('Http/Controllers')
            : $rootNamespace.'\\Http\\Controllers';
    }
    
    • Use Case: Maintain backward compatibility when --module is not specified.

Integration Tips

  • Leverage ModuleConfig Methods

    • $module->getNamespace('Path/To/Subdirectory'): Dynamically resolve namespaces.
    • $module->path: Get the base path of the module.
    • $module->name: Access the module name.
  • Extend Generator Stubs Modify stub files to include module-specific placeholders (e.g., {moduleNamespace}) and replace them in the generator:

    protected function replaceNamespace($stub, $name)
    {
        $stub = parent::replaceNamespace($stub, $name);
        return $this->module()
            ? str_replace('{moduleNamespace}', $this->module()->getNamespace('App'), $stub)
            : $stub;
    }
    
  • Customize Module Path Resolution Override the module() method in your command to use a custom module resolver:

    protected function module()
    {
        return app('module')->findByName($this->option('module'));
    }
    
  • Batch Processing with Modules Use the module trait to process multiple modules in a single command:

    $modules = app('module')->all();
    foreach ($modules as $module) {
        $this->line("Processing module: {$module->name}");
        // Command logic per module
    }
    

Gotchas and Tips

Pitfalls

  1. Missing internachi/modular Dependency

    • Issue: The package requires internachi/modular to be installed and configured. Without it, $this->module() will return null.
    • Fix: Ensure internachi/modular is installed and the ModuleServiceProvider is registered in config/app.php.
  2. Namespace Collisions

    • Issue: If a module’s namespace conflicts with the root namespace (e.g., both have App\Http\Controllers), generated files may overwrite each other.
    • Fix: Explicitly define namespaces in your generator:
      protected function getDefaultNamespace($rootNamespace = null)
      {
          return $this->module()
              ? $this->module()->getNamespace('Http/Controllers')
              : $rootNamespace.'\\Http\\Controllers';
      }
      
  3. Path Resolution in Non-PSR-4 Modules

    • Issue: Modules with custom directory structures may not resolve paths correctly.
    • Fix: Extend the ModuleConfig class or override path resolution in your command:
      $customPath = $module->path.'/Custom/Directory';
      
  4. Laravel 13+ Console Component Changes

    • Issue: Symfony 7.x console component updates may introduce breaking changes in argument/option handling.
    • Fix: Stay updated with the latest internachi/modularize releases and test commands after Laravel upgrades.
  5. Generator Command Caching

    • Issue: Cached generators may not reflect module-specific changes.
    • Fix: Clear the cache after updating generators:
      php artisan cache:clear
      php artisan view:clear
      

Debugging Tips

  • Verify Module Configuration Dump the module object to debug its properties:

    $module = $this->module();
    $this->line('<comment>Module:</comment> '.print_r($module, true));
    
  • Check for Missing Dependencies Ensure internachi/modular is installed and configured:

    composer show internachi/modular
    php artisan config:clear
    
  • Test Module Paths Validate module paths manually:

    $this->line('<info>Module Path:</info> '.$module->path);
    $this->line('<info>Namespace:</info> '.$module->getNamespace('App'));
    
  • Inspect Generator Output Use --verbose to debug generator behavior:

    php artisan make:widget --module=Blog --verbose
    

Extension Points

  1. Custom Module Resolver Override the module() method to use a custom resolver:

    protected function module()
    {
        return app('custom.module.resolver')->resolve($this->option('module'));
    }
    
  2. Dynamic Stub Replacement Extend stub replacement logic to include module-specific placeholders:

    protected function replaceModulePlaceholders($stub, $module)
    {
        return str_replace(
            ['{moduleName}', '{modulePath}'],
            [$module->name, $module->path],
            $stub
        );
    }
    
  3. Pre- and Post-Command Hooks Add hooks to execute logic before/after module detection:

    protected function beforeModuleDetection()
    {
        // Pre-module logic
    }
    
    protected function afterModuleDetection($module)
    {
        // Post-module logic
    }
    
  4. Module-Aware Argument Parsing Dynamically adjust argument parsing based on the active module:

    protected function getArguments()
    {
        $arguments = parent::getArguments();
        if ($this->module()) {
            $arguments['module-specific-arg'] = Input::argument('module-specific-arg');
        }
        return $arguments;
    }
    
  5. Fallback to Root for Missing Modules Handle cases where a module doesn’t exist by falling back to the root namespace:

    if (!$module = $this->module()) {
        $this->error('Module not found. Falling back to root namespace.');
        return parent::getDefaultNamespace($rootNamespace);
    }
    
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.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport