Drupal 9 has introduced a shift from procedural to object-oriented programming (OOP) and more extensive use of namespaces. For developers who have been away from Drupal or PHP for a while, this transition can be quite confusing. This blog post will discuss when to use services directly and when to use containers and OOP in Drupal.
Understanding Namespaces and the Leading Slash
The leading slash in \Drupal is related to PHP namespaces. It indicates that the class is located in the top-level namespace. Namespaces are a way to organize and group related code in PHP, and you can learn more about them in the official PHP documentation here. In Drupal 9, the \Drupal class refers to the main Drupal class that exposes various static helper functions to access services from the service container.
$line_max = \Drupal::state()->get('user_import_line_max');
Using Services Directly
Using services directly is suitable for procedural code, which is common in Drupal 7 and earlier versions. With the shift to OOP in Drupal 8 and 9, it is recommended to use dependency injection patterns in object-oriented code. However, using services directly can still be useful in certain situations, such as in custom module hooks or simple functions.
function mymodule_preprocess_page(&$variables) {
$site_name = \Drupal::state()->get('system.site')->get('name');
$variables['site_name'] = $site_name;
}
Using Containers and Object-Oriented Programming
In object-oriented code, it is recommended to use dependency injection patterns, such as constructor injection, to obtain service container objects. Dependency injection facilitates unit testing your classes and promotes better code organization. Here's an example of how to use dependency injection with the state service in a custom Drupal controller:
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\State\StateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class MyController extends ControllerBase {
protected $state;
public function __construct(StateInterface $state) {
$this->state = $state;
}
public static function create(ContainerInterface $container) {
return new static(
$container->get('state')
);
}
public function myControllerMethod() {
$line_max = $this->state->get('user_import_line_max');
// Do something with $line_max
}
}