Search by

echo-fusion / pluginmanager

amir-shadanfar

A flexible PHP package for managing and integrating plugins, allowing dynamic loading and registration based on application environments. Enhance the modularity and extensibility of your applications with ease.

Package info

github.com/echo-fusion/pluginmanager

pkg:composer/echo-fusion/pluginmanager

Statistics

Installs: 284

Dependents: 1

Suggesters: 0

Stars: 1

Open Issues: 0

v3.0.0 2026-10-12 12:20 UTC

README

CI Packagist PHP License

The PluginManager is a versatile package for managing and integrating plugins into your PHP applications. It allows you to dynamically load and register plugins based on the environment, making your application modular and extensible.

Part of EchoFusion, a modular PHP framework built from small packages.

Installation

composer require echo-fusion/pluginmanager

Requirements

  • PHP 8.1, 8.2 or 8.3

What a plugin is for

A plugin is an optional feature that is switched on for certain environments (dev, test, prod ...) and is given the container so it can wire itself in. Typical plugins: a debug bar or profiler only in dev, a fake mailer in test, an error tracker only in prod, a feature flag, or an add-on that attaches listeners and adds services.

It is not a service container (that is servicemanager, which decides how objects are built), and it differs from a module (modulemanager), which declares data: config, providers, routes, templates. A plugin runs code at start-up.

Usage

use EchoFusion\Contracts\PluginManager\PluginInterface;
use EchoFusion\Contracts\ServiceManager\SettableContainerInterface;
use EchoFusion\PluginManager\PluginManager;

final class DebugBarPlugin implements PluginInterface
{
    public function register(SettableContainerInterface $container): void
    {
        // use anything the container knows: attach a listener, add a service, replace an implementation
        $container->get(EventManagerInterface::class)->attach('response.ready', new DebugBarListener());
        $container->set(MailerInterface::class, fn () => new LogMailer());
    }

    public function getSupportedEnvironments(): array
    {
        return ['dev', 'test'];
    }
}

$pluginManager = new PluginManager($container, [DebugBarPlugin::class, new ErrorTrackerPlugin($sentry)]);
$pluginManager->register('dev');            // DebugBarPlugin::register() runs; plugins for other environments do not

$pluginManager->isRegistered(DebugBarPlugin::class);   // true
$pluginManager->getPlugin(DebugBarPlugin::class);      // the registered instance

$container is a SettableContainerInterface (a PSR-11 container that also has set()); servicemanager provides one.

Plugins by class name

A plugin can be an object or the class name of a plugin. A class name is built by the container (constructor dependencies are auto-wired) the first time register() needs it:

$pluginManager = new PluginManager($container, [
    DebugBarPlugin::class,          // built by the container
    new ErrorTrackerPlugin($sentry), // or an object you already have
]);
$pluginManager->register('dev');

The manager has to ask a plugin which environments it supports before it can skip it, so every plugin is built once even when it is not for the current environment. Keep plugin constructors cheap.

Behaviour worth knowing

  • register($environment) runs a plugin's register() once, only for plugins whose getSupportedEnvironments() contains the environment. Calling it again does not run them again.
  • getPlugin(Foo::class) returns the very instance that was registered (it does not ask the container for a new one), and throws PluginNotRegisteredException when that plugin was not registered for the current environment.

Testing

composer test

Credits

License

The MIT License (MIT). Please see LICENSE for more information.