Skip to content

whilesmartphp/laravel-plugin-engine

Repository files navigation

Laravel Plugin Engine

Tests License: MIT

A flexible and powerful plugin system for Laravel applications.

Features

  • Plugin discovery and registration
  • Enable/disable plugins
  • Plugin dependencies
  • Console commands for plugin management
  • Event-driven architecture
  • Easy to extend

Installation

  1. Install the package via Composer:
composer require whilesmart/laravel-plugin-engine
  1. Publish the configuration file (optional):
php artisan vendor:publish --provider="WhileSmart\LaravelPluginEngine\Providers\PluginServiceProvider" --tag=config

Configuration

Publish the configuration file:

php artisan vendor:publish --provider="WhileSmart\LaravelPluginEngine\Providers\PluginServiceProvider" --tag=config

Edit the config/plugins.php file to configure the plugin system:

return [
    'path' => base_path('plugins'),  // Path where plugins are stored
    'namespace' => 'Plugins',        // Root namespace for plugins

    'log_channel' => env('PLUGIN_ENGINE_LOG_CHANNEL'),       // Log channel, null = app default
    'log_level' => env('PLUGIN_ENGINE_LOG_LEVEL', 'warning'), // Minimum level the engine logs at
];

Logging

The engine logs through its own configurable channel and minimum level, independent of the application's logging:

  • PLUGIN_ENGINE_LOG_CHANNEL: any channel from config/logging.php. Leave unset to use the application's default channel.
  • PLUGIN_ENGINE_LOG_LEVEL: messages below this level are dropped. Defaults to warning, so routine discovery output stays out of production logs. Set to debug to trace plugin discovery and registration.

Usage

Available Commands

  • plugin:list - List all available plugins
  • plugin:info {id} - Show information about a plugin
  • plugin:enable {id} - Enable a plugin
  • plugin:disable {id} - Disable a plugin
  • plugin:install {package} - Install a plugin from a Composer package, a repository URL, or a local path
  • plugin:discover - Discover and register all available plugins
  • plugin:cache - Compile discovered plugins into a cache file
  • plugin:clear - Remove the plugin cache file

Plugin dependencies

When a plugin is installed from a URL or a local path, the engine reads the plugin's own composer.json and installs its require dependencies into the host application, so the plugin's classes are available at runtime.

For hosts that embed several plugins, enable wikimedia/composer-merge-plugin so each plugin keeps owning its dependencies while Composer resolves them together into the single host vendor/:

// host composer.json
"extra": {
    "merge-plugin": {
        "include": ["plugins/*/composer.json"]
    }
},
"config": {
    "allow-plugins": { "wikimedia/composer-merge-plugin": true }
}

With this configured, installing a plugin runs a targeted composer update; otherwise the engine falls back to composer require for the plugin's dependencies.

Caching

By default, plugins are discovered by scanning the plugins directory and parsing each manifest on every boot. In production, compile the result to a cache file instead, alongside the framework's other caches:

php artisan plugin:cache

The compiled file is loaded on boot and the filesystem scan is skipped. Run this on every deploy, next to config:cache and route:cache. plugin:enable, plugin:disable, and plugin:discover refresh an existing cache automatically. To return to live discovery:

php artisan plugin:clear

Creating a Plugin

  1. Create a new directory in the plugins directory (or your configured path)
  2. Create a plugin.json file with the following structure:
{
    "id": "example-plugin",
    "name": "Example Plugin",
    "description": "A sample plugin",
    "version": "1.0.0",
    "namespace": "Plugins\\Example",
    "provider": "Plugins\\Example\\ExampleServiceProvider",
    "enabled": true,
    "requires": {
        "php": ">=8.1",
        "laravel/framework": "^10.0"
    }
}
  1. Create a service provider for your plugin:
<?php

namespace Plugins\Example;

use Illuminate\Support\ServiceProvider;

class ExampleServiceProvider extends ServiceProvider
{
    public function register()
    {
        // Register bindings
    }

    public function boot()
    {
        // Boot logic
        $this->loadRoutesFrom(__DIR__.'/routes/web.php');
        $this->loadViewsFrom(__DIR__.'/resources/views', 'example');
        $this->loadMigrationsFrom(__DIR__.'/database/migrations');
    }
}

Plugin Structure

plugins/
  example-plugin/
    src/
      Http/
        Controllers/
      Models/
      Providers/
        ExampleServiceProvider.php
    resources/
      views/
    routes/
      web.php
    database/
      migrations/
    plugin.json
    README.md

Events

The plugin system dispatches several events that you can listen for:

  • WhileSmart\PluginEngine\Events\PluginEnabling - Fired before a plugin is enabled
  • WhileSmart\PluginEngine\Events\PluginEnabled - Fired after a plugin is enabled
  • WhileSmart\PluginEngine\Events\PluginDisabling - Fired before a plugin is disabled
  • WhileSmart\PluginEngine\Events\PluginDisabled - Fired after a plugin is disabled
  • WhileSmart\PluginEngine\Events\PluginInstalled - Fired after a plugin is installed
  • WhileSmart\PluginEngine\Events\PluginDiscovered - Fired when a plugin is discovered

Development

The repository ships a dockerized environment, so PHP and Composer are not required on the host:

make install   # build the container and install dependencies
make test      # run the test suite
make pint      # fix code style
make check     # run style check and tests
make shell     # open a shell in the container

License

This project is open-source and licensed under the MIT License.

About

A flexible and powerful plugin system for Laravel applications.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors