andyjameswhite's avatar

Modular Laravel - What to leave out of a module?

I'm looking for comments from people who have implemented Laravel in a modular way. (I'm not really wanting comments on the Pros and Cons of modularization in Laravel)

Where did you draw the line on what to include in the modules?

Typically I assume you're going to want to include Models, Controllers, Providers, Views, Policies, routes, config and any other custom Classes/Services/Interfaces/Actions/Queries.

So quite a lot.

But what about Events, Listeners, Notifications, Mail for example. I'm thinking they should probably go in the appropriate modules too as most of the time they will be quite obviously linked to a module's functionality?

This then just leaves a very lightweight app folder, which could perhaps just contain Commands, Middleware, Auth Controllers and possibly very generic stuff like Rules or Traits.

What are people's experiences here?

0 likes
4 replies
LaryAI's avatar
Level 58

When implementing a modular architecture in Laravel, the goal is to encapsulate functionality related to a specific domain or feature within its own module. This approach can help in organizing code, improving maintainability, and facilitating team collaboration. Here's a guideline on what to include in a module and what to leave out:

What to Include in a Module

  1. Models: Each module should contain its own models that are specific to its domain.

  2. Controllers: Controllers that handle requests related to the module's functionality should be included.

  3. Service Providers: If the module requires specific services or bindings, include a service provider to register them.

  4. Views: Any views that are specific to the module should be encapsulated within it.

  5. Routes: Define routes that are specific to the module within the module itself.

  6. Policies: If the module has specific authorization logic, include policies within the module.

  7. Config: Any configuration specific to the module should be included in a config file within the module.

  8. Custom Classes/Services/Interfaces/Actions/Queries: Any custom logic or services that are specific to the module should be included.

  9. Events and Listeners: If the module has specific events and listeners, they should be included within the module. This keeps event-driven logic encapsulated.

  10. Notifications and Mail: These should also be included in the module if they are specific to the module's functionality.

What to Leave Out of a Module

  1. Global Middleware: Middleware that applies to the entire application should remain in the main app/Http/Middleware directory.

  2. Auth Controllers: If authentication is a cross-cutting concern, it might be better to keep it in a central location unless you have module-specific authentication logic.

  3. Commands: If commands are specific to a module, they can be included within it. However, global commands should remain in the main app/Console/Commands directory.

  4. Generic Rules or Traits: If these are used across multiple modules, it might be better to keep them in a shared location, such as app/Rules or app/Traits.

Additional Considerations

  • Shared Resources: If multiple modules need to share resources, consider creating a shared module or a core module that can be used by other modules.

  • Testing: Each module should have its own tests to ensure its functionality is working as expected.

  • Naming Conventions: Use consistent naming conventions for modules to make it easier to navigate and understand the structure.

By following these guidelines, you can create a modular Laravel application that is well-organized and easy to maintain. Each module should be as self-contained as possible, with only truly global concerns left in the main application structure.

martinbean's avatar
Level 80

@andyjameswhite Why would you adopt a modular structure if you then looked for stuff to “leave out” of the modules…?

If I were to adopt a modular structure, then I’d put everything pertaining to that module in that module’s folder: commands, configuration, controllers, events, jobs, mailables, models, policies, routes, views, and so on. So your modules’ folders essentially become mini Laravel apps of their own, with a service provider to register its resources (configuration, routes, etc) in the main application’s service container.

It doesn’t make sense to say, “I’m going to have a Foo module, but these files relating to the Foo module I’m not going to bundle with the Foo module…”

I tend to stay away from modules because they’re always started with the best of intentions, but then people get stuck on which module things like users and other “global” or “shared” objects should live in, and then a horrible “shared” module gets created to hold miscellaneous stuff. But if I were to add them to a Laravel app, I’d put them inside maybe a src folder in the root directory of my application, with a sub-folder for each module, and then each module looking like a mini Laravel application like this:

.
├── app
└── src
    └── shop
        ├── config
        │   └── shop.php
        ├── resources
        │   └── views
        ├── routes
        │   ├── api.php
        │   └── web.php
        └── src
            ├── Console
            │   └── Commands
            ├── Events
            ├── Http
            │   ├── Controllers
            │   ├── Middleware
            │   └── Requests
            ├── Jobs
            ├── Mail
            ├── Models
            ├── Notifications
            ├── Policies
            └── ShopServiceProvider.php
andyjameswhite's avatar

Thanks @martinbean that first sentence was near enough the sanity check I needed.

I typically like the group by type approach that comes with Laravel, so have never attempted a modular version.

FWIW, this project is a bit different in that I have 3 very distinct areas with little shared functionality.

I was even considering having possibly 3 separate apps, but didn't feel the project was quite of the size to justify the overhead in maintaining those code bases.

It's the possibility these may well need to be separate apps, in the not too distant future to help scale etc that I've decided to go for the modular approach.

1 like

Please or to participate in this conversation.