Accessing services in plugins or other classesfor Drupal 8 , 9 , 10 , and 11

Last updated :  

Building on the previous lesson where we explored injecting services into controllers, today we delve into accessing those services within Drupal plugins or other classes. This topic is crucial for anyone aiming to develop more complex and feature-rich Drupal modules.

Understanding Services in Plugins

Drupal plugins are a way to encapsulate and organize reusable code and functionality. Like controllers, plugins often need access to services for performing operations like accessing the database, language translations, and more.

Service Injection Methodology

The general methodology for injecting services in plugins or other classes is quite similar to controllers. You use Drupal’s ServiceContainer, but with slight modifications specific to plugin structure.

Example Scenario: A Custom Block Plugin

In this lesson, we'll implement a block plugin that fetches and displays random user data from an external API using the HTTP client service.

Step 1: Define Your Custom Block Plugin

Create a Plugin/Block directory within your module and add a file named RandomUserBlock.php.


// weather_module/src/Plugin/Block/RandomUserBlock.php

namespace Drupal\weather_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use GuzzleHttp\ClientInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;

/**
 * Provides a 'Random User' Block.
 *
 * @Block(
 *   id = "random_user_block",
 *   admin_label = @Translation("Random User Block"),
 *   category = @Translation("Custom")
 * )
 */
class RandomUserBlock extends BlockBase implements ContainerFactoryPluginInterface {

  protected $httpClient;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, ClientInterface $http_client) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->httpClient = $http_client;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('http_client')
    );
  }

  public function build() {
    // Fetch a random user from randomuser.me API
    $response = $this->httpClient->get('https://randomuser.me/api/');
    $data = json_decode($response->getBody(), TRUE);
    $user = $data['results'][0];

    return [
      '#theme' => 'item_list',
      '#items' => [
        $this->t('Name: @name', ['@name' => $user['name']['first'] . ' ' . $user['name']['last']]),
        $this->t('Email: @email', ['@email' => $user['email']]),
      ],
    ];
  }
}

Step 2: Add the Block to Your Page

Add the newly created block to your Drupal site through the Block Layout page. Navigate to Admin > Structure > Block layout and place your "Random User Block" where desired.

Service Injection in Other Classes

The above pattern can also be utilized in other classes, such as forms, when extending FormBase or any other service-consuming class in your module. The rationale and syntax remain similar, using the constructor for injecting services.

Considerations for Efficient Service Use

Remember to always consider the efficiency and necessity of service calls. Overusing services without consideration can affect module performance. Aim to only fetch data you intend to display or manipulate immediately.

Conclusion and Next Steps

This lesson expanded on your knowledge of accessing services within plugins, with practical examples and step-by-step guidance. Remember that consistent patterns and understanding the core principles of service injection will greatly benefit your development process.

In our next lesson, we'll explore "Adding tags to services for event subscribers or collectors". This will further enable you to develop a dynamic and event-driven architecture in Drupal, enhancing your module's functionality.

Continue practicing, and see you in the next lesson!