2

I was reading the code comments in the StringTranslationTrait trait and saw the following:

If the class is capable of injecting services from the container, it should inject the 'string_translation' service and assign it to $this->stringTranslation.

So I created a simple service, used the StringTranslationTrait, injected the string_translation service and assigned it to $this->stringTranslation. I found that when I don't inject the string_translation service the $this->t() function still works as I expected.

Why should one inject said service into his own service? Is it good practice or are there other benefits such as speed? The comments in the StringTranslationTrait file offer no explanation.

My service for completeness:

<?php

namespace Drupal\wow\Service;

use Drupal\Core\Url;
use Drupal\Core\StringTranslation\TranslationInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Class RedirectService.
 *
 * @package Drupal\wow\Service
 */
class RedirectService {

  use StringTranslationTrait;

  /**
   * The redirect object.
   *
   * @var \Symfony\Component\HttpFoundation\RedirectResponse
   */
  private $redirectResponse;

  /**
   * RedirectService constructor.
   *
   * @param \Drupal\Core\StringTranslation\TranslationInterface $stringTranslation
   *   The string translation service.
   */
  public function __construct(TranslationInterface $stringTranslation) {
    $this->stringTranslation = $stringTranslation;
  }

  /**
   * Sets the redirect.
   *
   * @param string $routeName
   *   Drupal route name to redirect to.
   * @param string $message
   *   Message to show after redirecting. If not provided no message will be
   *   shown.
   * @param string $messageType
   *   Message type of message shown after redirecting.
   */
  public function setRedirect($routeName, $message = NULL, $messageType = 'status') {
    $uri = Url::fromRoute($routeName);

    if ($message) {
      drupal_set_message($this->t($message), $messageType);
    }

    $this->redirectResponse = new RedirectResponse($uri->toString());
  }

  /**
   * Gets the redirect object.
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse
   *   The redirect object.
   */
  public function getRedirect() {
    return $this->redirectResponse;
  }

  /**
   * Returns the response object.
   *
   * @return \Symfony\Component\HttpFoundation\Response
   *   The response object.
   */
  public function send() {
    return $this->redirectResponse->send();
  }

}

1 Answer 1

6

If you didn't inject the string translation service into $this->stringTranslation, the trait would get it from the static \Drupal wrapper

  /**
   * Gets the string translation service.
   *
   * @return \Drupal\Core\StringTranslation\TranslationInterface
   *   The string translation service.
   */
  protected function getStringTranslation() {
    if (!$this->stringTranslation) {
      $this->stringTranslation = \Drupal::service('string_translation');
    }

    return $this->stringTranslation;
  }

and this should be avoided in OOP code. The main reason for this is to be able to inject mock-up services for code tests.

1
  • 2
    Yes and no, the trait also defines a setStringTranslation() method, so even if you don't use constructor injection and at normal runtime, falls back to the container, you could still use that in a unit test. So, recommended, but not strictly necessary.
    – Berdir
    Commented Jun 30, 2017 at 22:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.