By Herman Peeren on Friday, 20 February 2026
Category: April 2026

Custom Plugins, part 1: General Overview

This is the start of a series of articles about building custom plugins. We will start with some general information about plugins and creating them. In subsequent episodes of this series we will take a closer look at specific plugin types and their peculiarities.

Procedural hooks and decoupled services

With plugins you can adjust components and extend their functionality. Basically there are two distinct mechanisms that are used by plugins:

Those procedural hooks are the oldest form of plugins. They are a simple kind of middleware. A disadvantage is that they are tightly coupled: there where those events are triggered, you have to know with what parameters those procedures are called and what values they return. Joomla mitigates that coupling by using events instead of direct callbacks.Those callbacks used to require a fixed parameter order; events avoid that. Those events contain the input variables in a standardised way. In principle the plugins don’t have a return value anymore, but you can modify input parameters or add a result array to them. So, you can still use “hooks” in Joomla, but they use events to reduce coupling.  

Plugin tutorial in developers manual

In the developers manual you’ll find a tutorial on how to make a plugin. There a basic content plugin serves as an example. In the manual you can also find some general information about how plugins work, and about plugin methods and events. I’ll add some background information in the following sections of this article  about the Subscriber Interface and about Dependency Injection.

Subscriber Interface

In former days we directly added a method to a plugin with the same name as the event, and with a fixed order of parameters for that specific event. Those methods were detected with reflection, which was slow with many plugins. By using the SubscriberInterface, we define which events the plugin will handle and what methods will do that. Those handler methods now have the event object as parameter. The SubscriberInterface defines no return value, but you can add a result array. You can even give priorities to those handlers, so you are no longer fully dependent on plugin load order.

Dependency Injection

Like all Joomla extensions, plugins use dependency injection. That is why we have the service provider file. Read the article about dependency injection to understand more on how that works. In the service provider the plugin itself is instantiated and all dependencies are injected into it, typically via setters. For instance, if your plugin needs an application object, the database and user-info, you’ll need something like this in your service provider:

$plugin->setApplication(Factory::getApplication());
$plugin->setDatabase($container->get(DatabaseInterface::class));
$plugin->setUserFactory($container->get(UserFactoryInterface::class));

In the plugin itself you can use getters to get those injected objects:
$this->getApplication(), $this->getDatabase(), etc.

The getter and setter for the Application-object is already implemented in the parent Joomla\CMS\Plugin\CMSPlugin. If you want to provide other objects, you’ll have to implement the setter and getter methods yourself. For a lot of basic objects there are traits available to implement those getters and setters. For instance, to provide a database, use the Joomla\Database\DatabaseAwareTrait, and to provide a user object use the Joomla\CMS\User\UserFactoryAwareTrait. Best practice is to declare which interface is implemented when using such a trait; in this case Joomla\Database\DatabaseAwareInterface and Joomla\CMS\User\UserFactoryAwareInterface respectively.

Different types of plugins in this series

In the coming episodes we plan to show custom plugins of the following types:

Leave Comments