Supporting plugins in your component
The event system in Joomla! allows for a flexible method for components, modules and plug-ins to communicate with other plug-ins by following the Observer pattern. This pattern is most easily described as a simple communication mechanism. The basic premise is that zero or more "observers" or "listeners" register themselves with the system for a certain, known event. During a specific point in an application's lifecycle, the "communicator" (in our case a component, module or plug-in) fires the event, passing some information to all the observers. The observers can then act on the information passed to them and optionally return a result to the communicator.
Joomla! Observer Implementation
Joomla! implements the Observer pattern at a global level through the JPlugin (Observer) and JEventDispatcher (Observable) classes. Anyone wanting to receive notification of events will create a plug-in that extends the
JPlugin class. Subclasses of
JPlugin will automatically register themselves to the global JEventDispatcher class when their plug-in category has been loaded (more on that later). The
JEventDispatcher class is used as a dispatching mechanism that receives events from the communicators and forwards them on to the listeners that have been loaded. For a full explanation of this it is recommended to read the Plugin Developer Overview
Why Become A Communicator
There may be times in your component's lifecycle when it would be nice to notify others that some action has taken place. For example, let's say you have a compact disk (CD) library component. You may decide that you would like to let others know when a new CD has been added to the library. In this case, you could document a well known event (
onCdAddedToLibrary for example) and at the appropriate time, trigger the event passing in information about the new CD that was added to the library. All plug-ins that have implemented that event will be notified with the information and can handle it as they see fit. Instant communication!
How To Become A Communicator
Since all the dispatching is handled by the Joomla! core, it is easy to become a communicator. In fact, it's really just a matter of loading a certain set of plug-ins and calling the trigger method of the
You may wonder how to know which set of plug-ins to load. That's up to you. Plug-ins are managed at a group level that is defined in the plug-in's XML deployment file. There are eight predefined plug-in groups and each plug-in group is meant to handle a different set of tasks. For example, there is a search plug-in group that is meant to handle searching and a user plug-in group meant to handle user specific functions such as adding and removing a user from the Joomla! system. These plug-in groups are only loaded when they are needed, namely by the communicator. So you can create your own plug-in group and call it whatever you want. Because your component is well-defined, all listeners will know exactly which plug-in group and events they should be listening for.
How To Trigger Events
This leads us to the meat of this article: how to trigger events so implementing plug-ins can act on them. The first thing you need to do is to load your plug-in group. This is done via the following code:
JPluginHelper::importPlugin( 'myplugingroup' );
This will load all enabled plug-ins that have defined themselves as part of your group. The next thing you need to do is get an instance of the
$dispatcher = JEventDispatcher::getInstance();
Notice two things here. First, we are using the
getInstance() method, not
new, to create a new instance. That is because we need to get the global singleton instance of the JEventDispatcher object that contains a list of all the plug-ins available.
Next, we need to trigger our custom event:
$results = $dispatcher->trigger( 'onCdAddedToLibrary', array( &$artist, &$title ) );
Here we have triggered the event
onCdAddedToLibrary and passed in the artist name and title of the track. Which and how many parameters you pass is up to you. Passing parameters by reference (using an
&) allows the plug-ins to change the variables passed in. All plug-ins will receive these parameters, process them and optionally pass back information. The calling code can access the returned values via the array
$results (each element corresponds to the result of one plugin).
You Are Defining An API
By offering events for plugins to respond to, you are effectively creating an API. Proper planning is extremely important – once you release your code, other developers will start to depend on your events' names and parameters. Changing them later will break compatibility with all the plugins that use them.
Load The Right Plugin Group
One thing to notice about the trigger method is that there is nothing defining which group of plug-ins should be notified. In actuality, all plug-ins that have been loaded are notified regardless of the group they are in. It's important to make sure you have an event name that does not conflict with any other plug-in group's event name. Most of the time this is not an issue because your component is the one that is loading the plug-in group, so you know which ones are loaded. However be aware that the system plug-in group is loaded very close to the beginning of the request. Make sure you don't have any event naming conflicts with the system events.