Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to structure a modular app in Laravel 5?

I would like to divide my application in modules. For instance, there would be a "core" modules that contains the basic login functionality, app layout/formatting (CSS etc), user management and a diary.

Later on I may create other modules like a contact manager that can easily be added or removed from the application.

There would be some logic in the apps navigation for determining which modules are present and to show/hide the links to them.

How can I do this in terms of directory structure, namespaces and anything else that's needed?


I am looking at creolab/laravel-modules but it states that it is for Laravel 4. Can I still use it with 5 in exactly the same way?

The documentation says to place models, controllers and views within each module directory, but how does this work with routes? Ideally I would like each module to have its own routes.php file. How will all of this work with the stuff in the http and the resources directory?


I was thinking of something like this:

Module idea

But I have no idea how I would get it to work.


I have just tried the tutorial here:

http://creolab.hr/2013/05/modules-in-laravel-4/

With no extra libraries etc, just pure Laravel 5.

I seem to have hit a brick wall with an error message:

FatalErrorException in ServiceProvider.php line 16: Call to undefined method Illuminate\Config\Repository::package() 

Regarding the following:

<?php namespace App\Modules;  abstract class ServiceProvider extends \Illuminate\Support\ServiceProvider {      public function boot()     {         if ($module = $this->getModule(func_get_args())) {             $this->package('app/' . $module, $module, app_path() . '/modules/' . $module);         }     }      public function register()     {         if ($module = $this->getModule(func_get_args())) {             $this->app['config']->package('app/' . $module, app_path() . '/modules/' . $module . '/config');  // Add routes             $routes = app_path() . '/modules/' . $module . '/routes.php';             if (file_exists($routes)) require $routes;         }     }      public function getModule($args)     {         $module = (isset($args[0]) and is_string($args[0])) ? $args[0] : null;          return $module;     }  } 

What is causing this and how can I fix it?


Got my head around this a bit more now. Got my package/module routes and views working which is great:

abstract class ServiceProvider extends \Illuminate\Support\ServiceProvider {      public function boot()     {         if ($module = $this->getModule(func_get_args())) {             include __DIR__.'/'.$module.'/routes.php';         }         $this->loadViewsFrom(__DIR__.'/'.$module.'/Views', 'core');     }      public function register()     {         if ($module = $this->getModule(func_get_args())) {          }     }      public function getModule($args)     {         $module = (isset($args[0]) and is_string($args[0])) ? $args[0] : null;          return $module;     }  } 

I have one last question, how would I load all my controllers from inside my package, much like how the loadViewsFrom() method works?

like image 482
imperium2335 Avatar asked Feb 12 '15 19:02

imperium2335


2 Answers

I seem to have figured it all out.

I'll post it here in case it helps other beginners, it was just about getting the namespaces right.

In my composer.json I have:

... "autoload": {     "classmap": [         "database",         "app/Modules"     ],     "psr-4": {         "App\\": "app/",         "Modules\\": "Modules/"     } } 

My directory and files ended up like this:

enter image description here

I got my Core module router.php to work by wrapping my controllers for that module in a group specifying the namespace:

Route::group(array('namespace' => 'Modules\Core'), function() {     Route::get('/test', ['uses' => 'TestController@index']); }); 

I imagine when I come to doing my models for the package it will be a similar case of getting the namespaces right.

Thanks for all your help and patience!

like image 171
imperium2335 Avatar answered Sep 19 '22 11:09

imperium2335


Solution:

Step1: Create Folder “Modules” inside “app/”


Step2: In Modules folder create your Module (Module1( suppose admin Module))

 Inside admin module : create the following folder    1. Controllers  (here will your controller files)  2. Views  (here will your View files)  3. Models  (here will your Model files)  4. routes.php (here will your route code in this file) 

Similarly, you can create multiple modules

Module2( suppose API ) -Controllers -Views -Models -routes.php 

Step3 : Create ModulesServiceProvider.php inside “Modules/” Folder


Step4 : Paste following code inside ModulesServiceProvider.php

<?php  namespace App\Modules;  /**  * ServiceProvider  *  * The service provider for the modules. After being registered  * it will make sure that each of the modules are properly loaded  * i.e. with their routes, views etc.  *  * @author kundan Roy <[email protected]>  * @package App\Modules  */  use Illuminate\Support\Facades\Route; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;  class ModulesServiceProvider extends ServiceProvider {      /**      * Will make sure that the required modules have been fully loaded      *      * @return void routeModule      */     public function boot() {         // For each of the registered modules, include their routes and Views         $modules=config("module.modules");          while (list(,$module)=each($modules)) {              // Load the routes for each of the modules              if (file_exists(DIR.'/'.$module.'/routes.php')) {                  include DIR.'/'.$module.'/routes.php';             }              if (is_dir(DIR.'/'.$module.'/Views')) {                 $this->loadViewsFrom(DIR.'/'.$module.'/Views',$module);             }         }     }      public function register() { }  } 

Step5 : Add following line inside ‘config/app.php’ file

App\Modules\ModulesServiceProvider::class, 

Step6 : Create module.php file inside ‘config’ folder

Step7 : Add following code inside module.php (path => “config/module.php”)

<?php  return [     'modules'=>[         'admin',         'web',         'api'     ] ]; 

Note : You can add your module name whichever you have created. Here there are modules.

Step8 : Run this command

composer dump-autoload 
like image 25
Kundan roy Avatar answered Sep 22 '22 11:09

Kundan roy