Josheli
  • Home
  • Blog
    • Knob
    • Running
    • Soccer
    • Technology
  • About
Knob , Technology

Laravel: Simple Method for Modules

by dv March 1, 2017 No Comments

In my day job, I maintain a fairly large-ish Laravel application. It started out as a few separate vanilla PHP web apps, which I consolidated onto Laravel 4, then upgraded to Laravel 5. I’ve added a few new apps to the suite as business needs arose.

In the Laravel 4 version, I used creolab/laravel-modules to, well, modularize, the various apps under one Laravel instance. It worked well with a few gotchas, but the package wasn’t updated for Laravel 5. At that point I looked at a couple other module packages, but in the end decided it was simple enough to add modules to Laravel.

Assume our namespace is “CorpName”.

Add your namespace to composer.json

...
"psr-4": {
	"App\\": "app/",
	"CorpName\\": "app/CorpName/"
}
...

Create a directory structure like the following:

Add your Service Provider to the ‘providers’ array in config/app.php

...
'CorpName\Core\Providers\CorpNameServiceProvider',
...

Create “app/CorpName/Core/Providers/CorpNameServiceProvider.php”:

<?php 

namespace CorpName\Core\Providers;

use Illuminate\Support\ServiceProvider;
use CorpName\Core\Bootstrap;

/**
 * Load the CorpName Bootstrap helper, which in turn loads the modules.
 * Wired up in app/config/app.php providers array
 */
class CorpNameServiceProvider extends ServiceProvider {

	/**
	 * Bootstrap the application services.
	 *
	 * @return void
	 */
	public function boot()
	{
		$this->app['CorpName']->boot();
	}

	/**
	 * Register the application services.
	 *
	 * @return void
	 */
	public function register()
	{
		//
		$this->app->singleton('CorpName', function($app)
		{
		    return new Bootstrap($app);
		});		
	}

}

Create “app/CorpName/Core/Bootstrap.php”:

<?php

namespace CorpName\Core;

use Illuminate\Foundation\Application;

/**
 * Bootstrap the modules. Called from the ServiceProvider
 */
class Bootstrap
{
  /**
   * IoC
   * @var \Illuminate\Foundation\Application
   */
  protected $app;

  public function __construct(Application $app)
  {
    $this->app = $app;
  }

  public function boot()
  {
    $this->loadModules();
  }

  /**
   * Scan the CorpName/Modules directory for Modules, and load them (routes, views, includes)
   */
  public function loadModules()
  {
    /**
     * @var \Illuminate\Contracts\Filesystem\Filesystem $disk
     */
    $disk = \Storage::disk('modules');
    $modules = $disk->directories();

    $modules_path = config('filesystems.disks.modules.root');

    foreach ($modules as $module)
    {
      $module_path = $modules_path . '/' . $module;

      //register routes
      if($disk->exists("{$module}/routes.php"))
      {
        include $module_path . '/routes.php';
      }

      //set up views
      if($disk->exists("{$module}/views"))
      {
        $this->app['view']->addNamespace($module, $module_path . '/views');
      }

      //include files
      if($disk->exists("{$module}/includes"))
      {
        $includes = $disk->files("{$module}/includes");
        foreach ($includes as $include)
        {
          if(substr($include, -4) == '.php')
          {
            include_once $modules_path . '/' . $include;
          }
        }
      }
    }
  }
}

Note that I’m using a “modules” storage “disk” configured in “config/filesystem.php”:

...
'modules' => [
	'driver' => 'local',
	'root'   => app_path().'/CorpName/Modules',
],
...

And…

That’s basically it. You’ll probably want a routes.php file in each module, and a views directory, but you can structure your Modules as you see fit. If you use migrations, you’ll need to add your module/migrations directory to the autoload classmap in composer.json:

...
"autoload": {
	"classmap": [
		"database",
		"app/CorpName/Modules/ModuleOne/migrations",
		"app/CorpName/Modules/ModuleTwo/migrations",
		"app/CorpName/Modules/ZeeAppModule/migrations"
	],
...

Also, views can be referenced by module name in your controller and blade templates:

Controller:

...
return view('ModuleOne::index', $this->data);
...

Blade:

...
@extends('ModuleOne::layouts.master')

@section('apphead')
  @include('ModuleTwo::partials.head')
@stop
...

This setup has been running in Laravel 5.0 and 5.1 for a year or so without problems. It could probably use some improvements, like caching, but it works as is.

Related Content:

  • Migrating a Laravel application to Symfony by Dv April 15, 2019 When I started at the day job about 6.5 years ago, I inherited a jumble of custom PHP/MySql web applications.…
  • Laravel, Composer and Optimize by Dv February 18, 2016 So I write these little tech snippets mostly as a personal journal for my future self. Anyway, got caught again…
  • Automated Testing with Codeception by Dv February 12, 2016 I gave a little presentation at work the other day on using automated testing in my Laravel project using Codeception.…
  • Dockerizing PHP apps and deploying to AWS Fargate Part 1 by Dv February 6, 2019 For the day job, I maintain four custom PHP apps in addition to several Drupal sites. Up until a couples…
  • Stupidly Simple, Static, Startpage for Self-hosted Services by Dv February 21, 2021 I mentioned the other day that I've been self-hosting some software services on a server in my basement. Well, I…
It's only fair to share...Share on facebook
Facebook
Share on twitter
Twitter
Share on email
Email
  • Previous Install Ubuntu on HP Laptop with UEFI and new SSD Hard Drive8 years ago
  • Next Still running? Still running.8 years ago

Leave a Reply

Your email address will not be published. Required fields are marked *

Popular Posts

  • Josheli, What Happened? (55,009)
  • Stupidly Simple, Static, Startpage for Self-hosted Services (29,603)
  • Running a Plex Media Server on an Old Laptop (25,800)
  • Simple Google Photos: A WordPress Plugin (22,729)
  • Only Say True Things (22,073)

Random Read

More Janky Snowboarding Video
I went to Eldora Ski Resort recently for a little solo snowboarding, and the weather…

Read More

Google Photo
Google Photo
Google Photo
Google Photo

Social Things

  • Family Vance
  • Texas Longhorns News

RSS From Familyvance

  • Snowshoeing at Brainard Lake
  • Fishing and Hiking at Golden Gate Canyon State Park
  • Rainbow Trout Fishing Report at Waneka Lake
  • Weightless Texas-Rig Plastic Worms at Sawhill Ponds and Coot Lake
  • Sawhill Ponds Fishing Report
2025 Josheli. Donna Theme powered by WordPress