Plugins: Overview

Plugins are discrete, reusable pieces of functionality that can be easily utilized by any number of Labrador Applications. There are a variety of built-in Plugin interfaces that, when implemented, allow you to easily hook into the operations of a Labrador Application. In addition, it is possible to fully customize the Plugin loading process with your own Plugin types... meaning it would be easy for you to come up with your own Plugin and have it hook into Labrador.

In this guide we'll go over a high-level overview of the Plugin and the corresponding Pluggable. For more details about how to hook into specific Labrador functionality please check out the Plugin related tutorials.

Plugin

The Plugin interface is incredibly simple to implement. It is just a marker interface that requires no methods to be implemented on it. Realistically you should not be implementing the Plugin interface directly but instead should be using one of the interfaces that extend Plugin. Additionally, it is important any custom Plugin types you create implements or extends the Plugin interface.

Pluggable

A Plugin needs something to plug into. That's where the Pluggable interface comes along. The Pluggable is ultimately responsible for managing the entire lifecycle of a Plugin; from registering it to handling appropriate loading procedures. The Application interface extends Pluggable, your app should be the only Pluggable you need to interact with for the vast majority of use cases. If you extend the AbstractApplication class all the responsibilities of the Pluggable will already be taken care of. In the normal use case you'll really only be responsible for registering the correct plugins for your application.

It is critical if you implement your own Pluggable interface that you handle a variety of use cases and potential problems. It is highly recommended that you use Labrador's PluginManager to delegate the responsibilities of the Pluggable. For more information please see the reference material, Deep Dive: Plugins & Pluggables.

Registering your Plugin

You register Plugins by providing the Pluggable the fully-qualified class name. This should happen during your bootstrapping process and MUST happen before Engine::run() is called. Attempting to register plugins after the engine has started will result in an exception. Continuing with the bootstrap file created in Getting Started, if you had a plugin called Acme\Foo\BarPlugin we'd register it on your application like so.

<?php

// ... all of the previous code from the Getting Started guide

$injector = (new DependencyGraph($logger))->wireObjectGraph();

// We want to use the $injector to make these objects to ensure appropriate dependencies are autowired
$app = $injector->make(HelloWorldApplication::class);
$engine = $injector->make(Engine::class);

$app->registerPlugin(BarPlugin::class);

$engine->run($app);

Ultimately your application's Auryn\Injector will instantiate your Plugin. If you require a dependency that isn't provided by another Plugin you should ensure that the appropriate object graph has been wired for the $injector. If you're looking for more details on how to wire up your application's dependencies that aren't provided by Plugins please check out Creating your DependencyGraph.

Plugin Loading

Plugins go through their loading process as one of the very first steps when you call Engine::run. Loading of Plugins happens asynchronously and your Plugins have opportunities to run asynchronous code before your Application starts. The complete loading process is beyond the scope of this document. The most important thing to note is that Plugin loading starts immediately when you call Engine::run and all Plugins MUST be registered before this happens. If you'd like more information on the Plugin loading process please check out Deep Dive: Plugins.

Next Steps

Next we recommend check out Plugins: Registering Services to learn how to create Plugins that can be used to easily share the same services.