Sharing your data
During our recent work on the GatherContent module, we received a feature request to allow other modules to modify the data we were saving. As this is not a very well known topic for non-contrib and non-core development, we decide to write a short blogpost about the different approaches in Drupal 7 and Drupal 8.
Drupal 7 is based on a hook system. This basically means that your module can define some hooks which can be implemented by other modules. Before you define your hook, you have to think about whether someone is going to change your data before it is saved or if they just want to perform some actions on it after saving.
If you want to let a user change some data before saving, you need to call the
drupal_alter function in your module. This function is defined in the includes.inc file as:
function drupal_alter($type, &$data, &$context1 = NULL, &$context2 = NULL, &$context3 = NULL)
The first parameter is the name of your hook, you can pass some data as reference in the other parameters. The type of parameter can be a string or an array of possible implementations, which is used by Form API in implementation of
hook_form_FORM_ID_alter. The type in this case is
In GatherContent, we implemented it this way:
hook_gathercontent_pre_node_save_alter hook. In the code it looks this way:
The other way of implementing the hook is by calling the
module_invoke_all function. The difference between using
module_invoke_all is that you can pass values into
module_invoke_all only as values, so you need to take care when saving your data, etc. In GatherContent we use this approach for hooks invoked after the node is saved, e.g.
hook_gathercontent_post_node_save. In code it looks this way:
If your module exposes a lot of hooks, you should consider implementing
hook_hook_info() as well. This hook allows you to define groups of hooks and a module implementing these hooks can place them into the
$module_name.$group.name.inc file, making the whole module better structured.
Related to Drupal 8 architectural changes, we can see a certain divergence from the usage of the hook system. Instead of hooks there is a new Event system adopted from Symfony.
The Event system basically consists of two parts, EventListener and EventDispatcher. EventDispatcher takes care of triggering all EventListeners.
For implementing your new event, you should create a class extending the
\Symfony\Component\EventDispatcher\Event class. In this class you should implement a constructor, so you can pass values into your Event, and getters, so you are able to reach them in your EventListener. All parameters are passed as reference to Event.
In your module you can dispatch this Event with the core service
event_dispatcher. This service implements the dispatch method, which takes the machine name of your event in the first parameter and the object of your event in the second parameter. In the GatherContent module it looks like this:
We store all our event identifiers in constants in the GatherContentEvents class with additional documentation of these events. The second argument is an instance of our event, code for this event can be found in the
If you want your module to have a reaction for this event, you need to subscribe for it. You do this by implementing the service in your module and in
$your_module.services.yml you need to tag this service with the
event_subscriber tag. Your class should implement
\Symfony\Component\EventDispatcher\EventSubscriberInterface and you have to implement the
getSubscribedEvents() function. In this function you simply return an array with events and methods, which will be called as a reaction to dispatching this events.
In Drupal 8 you can use still use the
module_invoke_all approach by calling
\Drupal::moduleHandler()->invokeAll(), but it’s recommended to use the Event system.
Generally, we think that the event approach is simpler to understand and very common outside the Drupal world. The only problem with events is that they’re more resource consuming, which might have an impact on performance.
Rules is one of the most sophisticated modules you can find in the drupal sphere. It can be used to build complex and flexible systems that respond to a specific event. The three most important components of the module are events, conditions and actions. A reaction rule always needs a specified event to happen on the site, but the action takes place only if the criteria match.