原文地址:
https://docs.acquia.com/articles/drupal-8-services-and-controllers
创建个控制器
我们已经创建了控制器,现在把服务追加进去。当 simple_example() 函数被调用时它会返回一个渲染数组。扩展基类总是个好办法。本例中我们的控制器扩展 ControllerBase 类。我们很快就会看到,这使我们能够访问服务。
<?php /** * @file * Contains \Drupal\service_example\ServiceExampleController. */ namespace Drupal\service_example\Controller; use Drupal\Core\Controller\ControllerBase; class ServiceExampleController extends ControllerBase { /** * {@inheritdoc} */ public function __construct() { } /** * {@inheritdoc} */ public static function create() { return new static( ); } public function simple_example() { return [ '#markup' => 'Hello World' ]; } }
向控制器追加服务
为了使服务生效,我们使用叫做依赖注入(dependency injection)的一种模式。当我们的对象被创建时,create() 函数被调用。create() 函数然后调 __construct() 函数。在对象被创建之后,simple_example() 函数被调用。Drupal 8 里,大多数控制器的 create() 函数会带有一个容器参数。简而言之,这个容器叫你可以访问服务。更多信息在之后课程里会涉及。create() 函数使用那个容器参数获得服务,并把服务传递给 __construct() 函数,之后 __construct() 会把服务存储为类变量。
如果听起来复杂的话,那么我们重新梳理下,追加一个服务的基本方法是这样:
- 在控制器内使用 create() 函数返回服务。
- 传递这个服务到 __construct() 函数。
- 把服务作为类变量存储起来。
public static function create(ContainerInterface $container) { return new static( $container->get('service_example.example_service') ); }
象我们提及的那样,create() 函数有一个 ContainerInterface 类型的参数。它有一个重要的函数 get(),我们用它得到服务对象。返回 new static() 本质上调用 __construct() 函数。现在我们只有一个参数,但你可以使用逗号分割的参数列表传递多个服务。
public function __construct(ServiceExampleService $serviceExampleService) { $this->serviceExampleService = $serviceExampleService; }
这个函数把传递过来的服务存储为一个变量。
/** * @var \Drupal\service_example\ServiceExampleService */ protected $serviceExampleService;
现在我们创建一个新的变量。使用额外的 class 类型,我们使用 use 描述符把他们声明在文件顶部。
use Drupal\service_example\ServiceExampleService; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface;
现在我们可以在 simple_example() 函数内使用服务的 getServiceExampleValue() 方法了。
public function simple_example() { return [ '#markup' => $this->serviceExampleService->getServiceExampleValue() ]; }
最终的 ServiceExampleController.php 文件:
<?php /** * @file * Contains \Drupal\service_example\ServiceExampleController. */ namespace Drupal\service_example\Controller; use Drupal\service_example\ServiceExampleService; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\DependencyInjection\ContainerInterface; class ServiceExampleController extends ControllerBase { /** * @var \Drupal\service_example\ServiceExampleService */ protected $serviceExampleService; /** * {@inheritdoc} */ public function __construct(ServiceExampleService $serviceExampleService) { $this->serviceExampleService = $serviceExampleService; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('service_example.example_service') ); } public function simple_example() { return [ '#markup' => $this->serviceExampleService->getServiceExampleValue() ]; } }
现在可以激活这个模块,看下 /examples/service-example/simple 的效果。