Chaos Stop the madness!

How to use Laravel Packages in OctoberCMS Plugins

This is just a quick guide on how to easily include Laravel Packages in OctoberCMS plugins.

NOTE: If you are trying to implement a Laravel Package that interacts with the authentication system the process to do so is much more complicated as October does not utilize Laravel’s authentication system at present time.

Laravel Packages are often more complicated than simple classes that you can include in your project wherever. They can offer several things that are relatively easy to manage within a barebones Laravel application such as configuration files, service providers, and aliases; however things get slightly more complicated when you wish to use these packages within an October plugin.

The first thing that you’ll need to do in order to use a Laravel Package within your plugin is to require it via composer. Create a composer.json file in your plugin’s folder, and then add the packages you wish to use to the require object. An example of a composer.json for an October CMS plugin that requires a Laravel Package is below:

{
  "name": "luketowers/oc-laravelpackagesexample-plugin",
  "type": "october-plugin",
  "description": "OctoberCMS plugin for demonstrating the use of Laravel Packages within October plugins",
  "homepage": "https://github.com/LukeTowers/oc-laravelpackagesexample-plugin",
  "authors": [
    {
      "name": "Luke Towers",
      "email": "[email protected]"
    }
  ],
  "require": {
    "mews/purifier": "~2.0"
  }
}

After you add your packages to composer.json, run composer update from the root of your project; this will pull those dependencies into your project so that you can use them. No need to run composer update or install from your plugin folder itself, if your plugin is being submitted to the October CMS marketplace the marketplace will generate the vendor folder for your plugin automatically.

Now, as far as package initial setup / installation goes, you can’t just run the default installation commands for the package and be done, you need to register service providers and aliases, and then also provide a method for your plugin to manage the configuration of that package. All of these things can be done within an October project relatively painlessly, but the tricky bit comes when you want to make sure that your plugin can actually be used on other people’s projects.

Never fear however, as October includes several easy ways to dynamically register the various components of the package. Below is a method that I’ve created that will easily register any Laravel packages for your plugin. Place this method in your plugin’s Plugin.php file, and then call it from the plugin’s boot() method (also in Plugin.php).

Also ensure that your Plugin.php includes the necessary facades at the top of the file below the namespace declaration as below:

use App;
use Config;
use Illuminate\Foundation\AliasLoader;
/**
 * Boots (configures and registers) any packages found within this plugin's packages.load configuration value
 *
 * @see https://luketowers.ca/blog/how-to-use-laravel-packages-in-october-plugins
 * @author Luke Towers <[email protected]>
 */
public function bootPackages()
{
    // Get the namespace of the current plugin to use in accessing the Config of the plugin
    $pluginNamespace = str_replace('\\', '.', strtolower(__NAMESPACE__));
    
    // Instantiate the AliasLoader for any aliases that will be loaded
    $aliasLoader = AliasLoader::getInstance();
    
    // Get the packages to boot
    $packages = Config::get($pluginNamespace . '::packages');
    
    // Boot each package
    foreach ($packages as $name => $options) {
        // Setup the configuration for the package, pulling from this plugin's config
        if (!empty($options['config']) && !empty($options['config_namespace'])) {
            Config::set($options['config_namespace'], $options['config']);
        }
        
        // Register any Service Providers for the package
        if (!empty($options['providers'])) {
            foreach ($options['providers'] as $provider) {
                App::register($provider);
            }
        }
        
        // Register any Aliases for the package
        if (!empty($options['aliases'])) {
            foreach ($options['aliases'] as $alias => $path) {
                $aliasLoader->alias($alias, $path);
            }
        }
    }
}

Now, you can load any packages you want by including them in your plugin’s configuration file, which is located here: /plugins/vendorName/pluginName/config/config.php.

Any packages found in the ‘vendorName.pluginName::packages’ config value will be loaded. Below is an example of a config.php file that is configured to load the mews/purifier Laravel package.

<?php return [
    // This contains the Laravel Packages that you want this plugin to utilize listed under their package identifiers
    'packages' => [
        'mews/purifier' => [
            // Service providers to be registered by your plugin
            'providers' => [
                '\Mews\Purifier\PurifierServiceProvider',
            ],

            // Aliases to be registered by your plugin in the form of $alias => $pathToFacade
            'aliases' => [
                'Purifier' => '\Mews\Purifier\Facades\Purifier',
            ],

            // The namespace to set the configuration under. For this example, this package accesses it's config via config('purifier.' . $key), so the namespace 'purifier' is what we put here
            'config_namespace' => 'purifier',
            
            // The configuration file for the package itself. Start this out by copying the default one that comes with the package and then modifying what you need.
            'config' => [
                'encoding'      => 'UTF-8',
                'finalize'      => true,
                'cachePath'     => storage_path('app/purifier'),
                'cacheFileMode' => 0755,
                'settings'      => [
                    'default' => [
                        'HTML' => [
                            'Doctype'             => 'XHTML 1.0 Strict',
                            'Allowed'             => 'div,b,strong,i,em,a[href|title],ul,ol,li,p[style],br,span[style],img[width|height|alt|src]',
                        ],
                        'CSS'  => [
                            'AllowedProperties'   => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
                        ],
                        'AutoFormat' => [
                            'AutoParagraph' => true,
                            'RemoveEmpty'   => true,
                        ],
                    ],
                    'test'    => [
                        'Attr' => ['EnableID' => true]
                    ],
                    "youtube" => [
                        "HTML" => ["SafeIframe" => 'true'],
                        "URI"  => ["SafeIframeRegexp" => "%^(http://|https://|//)(www.youtube.com/embed/|player.vimeo.com/video/)%"],
                    ],
                ],
            ],
        ],
    ],
];

And that’s it! It’s just that easy! Drop me a line at [email protected] if you found it helpful or if you are looking for any assistance with your October CMS related shenanigans 🙂

Repository for this post is available on my Github

Get in touch today!