官术网_书友最值得收藏!

Injecting the service into our Controller

We have now closed the parenthesis on how services can be used. Let's take a look at how to inject our newly created service into our Controller.

We will need to add some code to our Controller (typically at the beginning of the class so that we can immediately identify the presence of this code when looking at it):

 /**
* @var \Drupal\hello_world\HelloWorldSalutation
*/
protected $salutation;

/**
* HelloWorldController constructor.
*
* @param \Drupal\hello_world\HelloWorldSalutation $salutation
*/
public function __construct(HelloWorldSalutation $salutation) {
$this->salutation = $salutation;
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('hello_world.salutation')
);
}

In addition to this, ensure that you include the relevant use statements at the top of the file:

use Drupal\hello_world\HelloWorldSalutation;
use Symfony\Component\DependencyInjection\ContainerInterface;

So, what is going on here? First, we give the Controller a constructor method, which takes our service as an argument and stores it as a property. For me, this is usually the very first method in the class, but how does this constructor get its argument? It gets it via the create() method, which receives the Service Container as a parameter and is free to choose the service(s) needed by the Controller constructor. This is usually my second method in a class. I prefer this order because it's very easy to check whether they are present. Also, their presence is important, especially when inheriting and observing what the parent is injecting, but how does this injection business work in reality?

In a nutshell, after the route is found and the responsible Controller is resolved, a check is made to see whether the latter implements ContainerInjectionInterface. Our Controller does so via its parent ControllerBase. If it does, the Controller gets instantiated via the create() method and the container is passed to it. From there, it is responsible for creating a new static version of itself with the required services from the container--not that complicated, really!

The create() method is a staple practice in the Drupal 8 dependency injection pattern, so you will see it quite a lot. However, one thing to keep in mind is that you should never pass the entire container to the class you instantiate with it because you are no longer doing dependency injection then.

A note about ControllerBase, which we are extending--it is a standard practice to extend it. It provides some nice traits, implements interfaces that are required and shows what the class purpose is immediately. However, from the point of view of dependency injection, I advise against using the helper methods that return services (for example, entityManager()). They, unfortunately, load services statically, which is not the best practice in this case. You should instead inject them yourself as we did earlier in this chapter.

Okay, now to turn back to our example. Now that we have the service injected, we can use it to render the dynamic salutation:

    return [
'#markup' => $this->salutation->getSalutation(),
];

There we have it. Now, our greeting is dependent on the time of day and our Controller is dependent on our salutation service.

One thing I would like to specify about our example is that I disregarded caching for the sake of simplicity. With the cache turned on, the page would be cached and served with potentially the wrong salutation. However, we'll have an entire chapter dedicated to caching, where we will cover all these intricacies, so there is no point in complicating our example.

主站蜘蛛池模板: 托克托县| 利津县| 灵石县| 平顺县| 阳谷县| 陵川县| 金湖县| 安陆市| 疏附县| 韶山市| 上高县| 玉溪市| 望奎县| 屯昌县| 类乌齐县| 静宁县| 固阳县| 河东区| 河北区| 苗栗县| 东光县| 天峻县| 三原县| 桂东县| 寿阳县| 凌海市| 玉溪市| 土默特左旗| 应城市| 乡宁县| 惠来县| 新巴尔虎左旗| 常州市| 宣汉县| 芦溪县| 尼木县| 蒙城县| 桑日县| 定南县| 孝昌县| 绥芬河市|