8.2 服务和控制器
创建个控制器
我们已经创建了控制器,现在把服务追加进去。当 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 描述符把他们声明在文件顶部。
现在我们可以在 simple_example() 函数内使用服务的 getServiceExampleValue() 方法了。
public function simple_example() {
return [
'#markup' => $this->serviceExampleService->getServiceExampleValue()
];
}
最终的 ServiceExampleController.php 文件(见辅助内容区):
现在可以激活这个模块,看下 /examples/service-example/simple 的效果。
<?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()
];
}
}