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

Modular Laravel Package

internachi/modular

A lightweight module system for Laravel using Composer path repositories and Laravel package discovery. Organize large apps by placing self-contained “modules” in an app-modules/ directory, following standard Laravel package conventions with minimal extra tooling.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require internachi/modular
    
    • No additional setup required; Laravel auto-discovers the package.
  2. Publish Config (Recommended)

    php artisan vendor:publish --tag=modular-config
    
    • Customize the default module namespace (e.g., InterNACHI\) in config/modular.php.
  3. Create Your First Module

    php artisan make:module blog
    
    • This scaffolds a module in app-modules/blog/ with:
      • composer.json (path repository entry + dependency)
      • src/, tests/, routes/, resources/, database/ directories.
    • Update dependencies:
      composer update modules/blog
      
  4. Sync Project Configs (Optional but Useful)

    php artisan modules:sync
    
    • Updates phpunit.xml and PhpStorm configs to recognize modules.

First Use Case: Adding a Module Controller

php artisan make:controller Blog/PostController --module=blog
  • Generates app-modules/blog/src/Http/Controllers/PostController.php.
  • Registers the controller automatically (no manual RouteServiceProvider changes).
  • Access routes via routes/blog.php (auto-loaded).

Implementation Patterns

1. Modular Development Workflow

  • Directory Structure:
    app-modules/
      ├── blog/
      │   ├── src/               # Core logic (controllers, services, etc.)
      │   ├── resources/         # Views, Lang, Assets
      │   ├── database/          # Migrations, Seeders, Factories
      │   └── routes/            # Module-specific routes
      └── forum/
    
  • Key Files:
    • composer.json: Defines the module as a path repository and dependency.
    • src/ModuleServiceProvider.php: Auto-generated; bootstraps module services.

2. Leveraging Laravel Conventions

Feature Usage in Modules Example
Routes routes/blog.php → Auto-loaded via RouteServiceProvider. Route::get('/posts', [PostController::class, 'index']);
Migrations Run with php artisan migrate. php artisan make:migration create_posts_table --module=blog
Factories Auto-discovered for factory(). Blog\Post::factory()->create();
Policies Auto-discovered for authorization. php artisan make:policy PostPolicy --module=blog
Blade Components Namespace: <x-blog::component />. app-modules/blog/src/View/Components/PostCard.php
Translations Namespace: __('blog::messages.welcome'). resources/lang/en/messages.php
Commands Auto-registered with Artisan. php artisan make:command SendNewsletter --module=blog
Seeders Run with --module: php artisan db:seed --module=blog. Blog\Database\Seeders\DatabaseSeeder

3. Integration Tips

  • Shared Services: Use Laravel’s bind() in ModuleServiceProvider to share services across modules:
    public function register()
    {
        $this->app->bind('blog.service', function () {
            return new BlogService();
        });
    }
    
  • Cross-Module Dependencies: Declare module dependencies in composer.json:
    "require": {
        "modules/blog": "*",
        "modules/forum": "*"
    }
    
  • Testing: Modules are auto-included in PHPUnit. Use:
    $this->module('blog')->actingAs($user)->get('/posts');
    
    (Requires laravel-shift/testing or similar.)

4. Customizing Module Generation

Publish stubs to override default scaffolding:

php artisan vendor:publish --tag=modular-stubs

Edit config/app-modules.php to customize:

'stubs' => [
    'module' => 'custom-path/stubs/module.stub',
],

Gotchas and Tips

Pitfalls

  1. Namespace Conflicts:

    • Avoid naming modules with reserved Laravel names (e.g., Auth, Cache).
    • Fix: Use a unique prefix (e.g., InterNACHI\Blog).
  2. Composer Path Repository:

    • Modules must be in app-modules/. Moving them breaks auto-discovery.
    • Fix: Re-run composer update modules/{module} after moving.
  3. Windows Path Issues:

    • Use forward slashes (/) in paths or normalize with str_replace('\\', '/', $path).
    • Fix: Run composer update after changes.
  4. Livewire Integration:

    • Only works if Livewire is installed (composer require livewire/livewire).
    • Fix: Skip --module flag or install Livewire first.
  5. PhpStorm IDE Issues:

    • Modules may not appear in IDE autocomplete.
    • Fix: Run php artisan modules:sync or manually add app-modules/* to PhpStorm’s "Project Root."
  6. Caching Quirks:

    • Clear module cache after changes:
      php artisan modules:clear
      php artisan config:clear
      

Debugging Tips

  1. Check Module Loading:

    php artisan modules:list
    
    • Lists loaded modules and their paths.
  2. Verify Auto-Discovery:

    • Ensure composer.json has the path repository entry:
      "repositories": [
          { "type": "path", "url": "app-modules/*" }
      ]
      
    • Run composer dump-autoload if changes aren’t reflected.
  3. Route Debugging:

    • Use php artisan route:list to confirm module routes are registered.
    • Common Issue: Forgetting to define routes in routes/{module}.php.
  4. Translation Debugging:

    • Ensure language files are in resources/lang/{locale}/ within the module.
    • Fix: Use __('module::key') (e.g., __('blog::messages.welcome')).
  5. Factory Debugging:

    • Factories must be in database/factories/ and named {Model}Factory.php.
    • Fix: Run php artisan make:factory PostFactory --module=blog.

Extension Points

  1. Custom Module Commands: Extend the make:module command by publishing stubs or overriding the ModuleMaker class.

  2. Dynamic Module Loading: Use the Modules facade to conditionally load modules:

    if (Modules::isEnabled('blog')) {
        // Load blog-specific services
    }
    
  3. Module Events: Dispatch events from modules:

    event(new PostPublished($post));
    
    • Listeners in src/Events/ are auto-discovered.
  4. API Resources: Generate resources with --module:

    php artisan make:resource PostResource --module=blog
    
    • Place in src/Http/Resources/.
  5. Middleware: Register module-specific middleware in ModuleServiceProvider:

    protected $middleware = [
        \Blog\Http\Middleware\VerifyBlogAccess::class,
    ];
    

Pro Tips

  • Extract Modules to Packages: Move app-modules/blog/ to a vendor package (e.g., internachi/blog) and update composer.json:

    "repositories": [
        { "type": "path", "url": "vendor/internachi/blog" }
    ],
    "require": {
        "internachi/blog": "dev-main"
    }
    
    • Re-run composer update.
  • Shared Config: Use config('modular.module_namespace') to dynamically reference modules.

  • Module-Specific Assets: Publish assets with:

    php artisan vendor:publish --tag=blog-assets --module=blog
    
    • Define in ModuleServiceProvider:
      public function boot()
      {
          $this->loadViewsFrom(__DIR__.'/../../resources/views', 'blog');
      }
      
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.
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
ecotone/kafka
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata