What is Autowiring? how to use Autowire in Drupal 8

What is Autowiring? how to use Autowire in Drupal

Posted on Thu, 01/10/2019 - 15:09 by yuseferi

 

I heard about the autowiring concept several years ago in spring java, 

 

Autowiring feature of spring framework enables you to inject the object dependency implicitly. It internally uses setter or constructor injection.

in Symfony 2.8, in November 2015, the autowiring concept introduced in a PHP framework for the first time.

Autowiring allows to register services in the container with minimal configuration. It automatically resolves the service dependencies based on the constructor's typehint which is useful in the field of Rapid Application Development, when designing prototypes in early stages of large projects. It makes it easy to register a service graph and eases refactoring.

 

That's right instead of explicit inject services as arguments in a service definition let Symfony detect the injected services arguments by their definitions on the constructor.

 

for example, we have the following service

namespace AppBundle\Service;

use Psr\Log\LoggerInterface;

class CustomService
{
    private $logger;

    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}

 in this situation, we had to explicitly inject the logger service as an argument on the service definition

# app/config/services.yml
services:
    customservice:
        class: AppBundle\Service\CustomService
        arguments: ['@logger']

So, each time we injected another Service to our service we had to add it as an argument in its service yml file but set "autowire: true" on service yml make it automatic. it means you do not need to concern about have you added new injected service in service yml definition or not? all you need is add your service to the constructor then it automatically detected by the injected service type definition.

 

I'm going to extend the first sample to inject Cache service as well.

 

namespace AppBundle\Service;

use Psr\Log\LoggerInterface;
use Psr\SimpleCache\CacheInterface;

class CustomService
{
    private $logger;
    private $cache;

    public function __construct(LoggerInterface $logger, CacheInterface $cache)
    {
        $this->logger = $logger;
        $this->cache = $cache;
    }
}

 

with Autowiring feature we don't need to add it to the service yml, in this situation the service yml  will be

# app/config/services.yml
services:
    customservice:
        class: AppBundle\Service\CustomService
         autowire: true

that's cool, isn't?

 

How to use Autowiring in Drupal 8?

Autowire feature has been introduced on Symfony 2.8. With considering this note that "Drupal 8.2" has used "Symfony 2.8" components and "Drupal 8.6" is using   "Symfony services  3.4 components" So we have this feature on Drupal > 8.2.

 

 

Example of autowiring on Drupal 8 :

an example to create a new service based on language and date services.

# on autowire_example/autowire_example.info.yml
name: Autowire Example
description: Provides a service to demonstrate service autowiring on Drupal 8
type: module
package: Example
core: 8.x
# on autowire_example/autowire_example.service.yml

services:
  example.example_service:
    class: Drupal\autowire_example\ExampleService
    autowire: true
# on autowire_example/src/ExampleService.php

<?php
/**
 * Created by PhpStorm.
 * User: yms
 * Date: 1/10/19
 * Time: 16:42
 */

namespace Drupal\autowire_example;

use Drupal\Core\Language\LanguageManagerInterface;
use \Drupal\Core\Datetime\DateFormatterInterface;

class ExampleService {

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $language_manager;

  /**
   * The Date Formatter
   *
   * @var \Drupal\Core\Datetime\DateFormatterInterface
   */
  protected $dateService;

  /**
   * Constructs a new FancyService.
   *
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Drupal\Core\Datetime\DateFormatterInterface $dateService
   *   The Date Formatter.
   *
   */
  public function __construct(LanguageManagerInterface $language_manager, DateFormatterInterface $dateService) {
    $this->language_manager = $language_manager;
    $this->language_manager = $dateService;
  }

  /**
   * Get Date Current Language.
   *
   * @param  integer $timestamp
   *   Date in timestamp.
   * @param  string date format
   *   Date fromat in string.
   *
   * @return string
   */
  public function getTranslatedDate($timestamp, $format) {
    $lang_code = $this->language_manager->getCurrentLanguage()->getId();
    return $this->language_manager->format($timestamp, 'custom', $format, NULL, $lang_code);
  }

}

 

Gitub Source of this sample 

Notes About Autowiring:

 

There are a few things you should keep in mind about using autowiring:

They do not work on scalar type hints, only objects. Meaning you cannot autowire strings, ints or booleans for example. Symfony will automatically throw an exception in case it runs into this.

Contrary to many people’s believes, autowiring does not impose a performance hit since all services are eventually compiled into a cacheable container file. However, when in dev mode, it might recompile more often when you modify classes but unless you have very large projects, that should not be a problem.

There is absolutely no need to use autowiring. Everything with autowiring can be done with manually defining services too. Autowiring just removes the need to write large service files with boilerplate. You are not missing anything out when you opt for not using autowiring.

Autowiring is not magic. It’s just Symfony trying to automatically inject services with other services based on their fully qualified class name.

 

References and Additionals :

New in Symfony 2.8/3.0: services autowiring

Defining Services Dependencies Automatically (Autowiring)

Autowiring on PHP-DI