Skip to main content
Home
Drupal life hacks

Main navigation

  • Drupal
  • React
  • WP
  • Contact
  • About
User account menu
  • Log in

Breadcrumb

  1. Home

Practical Use Cases of Tagged Services in Drupal

By admin, 24 September, 2024

In Drupal, "tagged services" allow you to categorize and manage service definitions by assigning them specific tags. These tags help the service container understand the purpose of certain services, often to group them for a specific function. Tagged services are typically used with "collector services," which gather services with the same tag and utilize them for a specific purpose.

How Tagged Services Work:

1. Defining a Service with a Tag:
  When defining a service in a *.services.yml file, you can apply a tag like this:

 yaml
  services:
    my_module.some_service:
      class: Drupal\my_module\SomeService
      tags:
        - { name: my_tag_name }

 In this example, my_module.some_service is tagged with my_tag_name. This tag can then be used to collect and process services related to this tag.

2. Using a Collector Service:
  A collector service will usually look for all services with a specific tag and group them together. You can inject a tagged service into the collector service:

 yaml
  services:
    my_module.collector_service:
      class: Drupal\my_module\CollectorService
      arguments: ['@service_container']

 Inside the collector service class, you can fetch tagged services like this:

 namespace Drupal\my_module;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 class CollectorService {
   protected $services;
   public function __construct(ContainerInterface $container) {
      // Collect all services tagged with "my_tag_name"
      $this->services = $container->findTaggedServiceIds('my_tag_name');
    }
   public function getServices() {
      return $this->services;
    }
  }

Common Use Cases:

- Event Subscribers: You can tag services as event subscribers, allowing Drupal to listen for certain events and respond accordingly.
- Plugin Managers: Often plugin managers use tags to collect all plugin implementations.
- Command Services: For custom commands, tagging services allows them to be picked up by Drupal's command system.

In essence, tagging services is a way of organizing and structuring how the service container can group and utilize services, making Drupal's service-oriented architecture more modular and extendable.

Here are several practical examples of using tagged services in Drupal to help better understand their application.

1. Event Subscribers

Tagged services are often used to create event subscribers. For example, if you want to track events such as new content creation or user profile updates, you can create a service and subscribe it to the corresponding event.

Example:


1. Creating an Event Subscriber:

 Define a service with the event_subscriber tag in the *.services.yml file:

 yaml
  services:
    my_module.event_subscriber:
      class: Drupal\my_module\EventSubscriber\MyEventSubscriber
      tags:
        - { name: event_subscriber }
 

2. Event Subscriber Class:

 This class will respond to the event, for instance, when a new node is created:

 namespace Drupal\my_module\EventSubscriber;
 use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  use Drupal\node\NodeInterface;
  use Drupal\node\NodeEvents;
 class MyEventSubscriber implements EventSubscriberInterface {
   public static function getSubscribedEvents() {
      $events[NodeEvents::INSERT][] = ['onNodeInsert'];
      return $events;
    }
   public function onNodeInsert(NodeInterface $node) {
      // Action upon node insertion
      \Drupal::logger('my_module')->info('New node created: ' . $node->getTitle());
    }
  }
 

In this example, the service is tagged as an event_subscriber, allowing Drupal to subscribe it to the NodeEvents::INSERT event.

2. Plugin Discovery

Tagged services can be used for plugin discovery and management. For instance, if you're building a module that adds a new type of plugin (like custom forms or payment gateways), you can use tags to register them automatically.

Example:


1. Defining Plugins with Tags:

 In your module, create a plugin and register it using a tag:

 yaml
  services:
    my_module.payment_gateway:
      class: Drupal\my_module\Plugin\PaymentGateway\MyPaymentGateway
      tags:
        - { name: payment_gateway }
 

2. Plugin Class:

 Create a plugin class that implements the plugin interface:

 namespace Drupal\my_module\Plugin\PaymentGateway;
 use Drupal\my_module\PaymentGatewayInterface;
 class MyPaymentGateway implements PaymentGatewayInterface {
   public function processPayment($amount) {
      // Logic for processing payment
    }
  }
 

3. Using a Plugin Manager to Discover Services:

 Create a plugin manager that collects all plugins with the payment_gateway tag:

 namespace Drupal\my_module;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 class PaymentGatewayManager {
   protected $gateways;
   public function __construct(ContainerInterface $container) {
      $this->gateways = $container->findTaggedServiceIds('payment_gateway');
    }
   public function getGateways() {
      return $this->gateways;
    }
  }
 

3. Creating Middleware

Tagged services can be used to create middleware that processes every request before it reaches the main controller.

Example:


1. Defining Middleware with Tags:

 Define middleware as a service with the http_middleware tag:

 yaml
  services:
    my_module.middleware:
      class: Drupal\my_module\Middleware\MyMiddleware
      tags:
        - { name: http_middleware }
 

2. Middleware Class:

 The middleware class should implement the HttpKernelInterface:

 namespace Drupal\my_module\Middleware;
 use Symfony\Component\HttpFoundation\Request;
  use Symfony\Component\HttpFoundation\Response;
  use Symfony\Component\HttpKernel\HttpKernelInterface;
 class MyMiddleware implements HttpKernelInterface {
   protected $httpKernel;
   public function __construct(HttpKernelInterface $httpKernel) {
      $this->httpKernel = $httpKernel;
    }
   public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) {
      // Request processing logic
      if ($request->getPathInfo() == '/custom-path') {
        return new Response('Custom response for /custom-path');
      }
     return $this->httpKernel->handle($request, $type, $catch);
    }
  }
 

4. Setting Up Cron Tasks Using Tags

Tagged services can also be used to register cron tasks. This allows you to create tasks that will automatically run when Drupal's cron is executed.

Example:


1. Registering a Cron Task:

 In the *.services.yml file, register a service with the cron tag:

 yaml
  services:
    my_module.cron_service:
      class: Drupal\my_module\Cron\MyCronService
      tags:
        - { name: cron }
 

2. Cron Task Class:

 Create a class that implements the logic for the cron task:

 namespace Drupal\my_module\Cron;
 class MyCronService {
   public function run() {
      // Execute the cron task logic
      \Drupal::logger('my_module')->info('Cron task executed.');
    }
  }
 

5. Setting Up Custom Drush Commands

Drush commands can also be registered using tagged services. This makes it easy to add new commands to the existing ones.

Example:


1. Registering a Drush Command with a Tag:

 In *.services.yml, register a Drush command:

 yaml
  services:
    my_module.drush_command:
      class: Drupal\my_module\Drush\MyDrushCommand
      tags:
        - { name: drush.command }
 

2. Command Class:

 Create a class that describes the logic of the command:

 namespace Drupal\my_module\Drush;
 use Drush\Commands\DrushCommands;
 class MyDrushCommand extends DrushCommands {
   /**
     * Execute the "my-custom-command".
     *
     * @command my-module:custom-command
     */
    public function customCommand() {
      $this->output()->writeln('My custom Drush command.');
    }
  }
 

Conclusion

Tagged services in Drupal greatly simplify the extension of system functionality and allow easy integration of new features through flexible and modular mechanisms. These examples are just a small part of how you can use tagged services to create more powerful and modular applications.

This should give you a clear idea of how tagged services are practically applied in Drupal. Let me know if you'd like to explore any of these examples further!

Tags

  • #Drupal Planet
  • Tagged Services

Comments

About text formats

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.
Powered by Drupal