(控制器)怎样去定义一个控制器为服务

在book文档里,你已经学习了如何让你的一个Controller去继承基类Controller。这个工作方式很好,但是还有别的方式例如把Controller指定为一个服务。

指定一个控制器作为服务需要做一点工作。这样做的主要优势是全部的Controller和任何服务都能通过Controller使用,只需要修改服务容器配置。开发一个开源的软件包或给不同的项目使用时,他非常方便。
第二个优势,通过观察构造函数参数,很容易看出他使用什么类型的东西,也知道这个控制器能做或不能做的事情。而且很明显(也就是说,如果你有很多的构造参数时)由于每个依赖都需要手动注入,控制器已经变得过于庞大,你就可以分割成多个控制器。
所以,即使你没有指定控制器为一个服务,你也会从一些开源的symfony的程序中看到。很重要的是你要了解这两种方式的优劣性。

定义这个控制器为一个服务

一个控制器可以和其他类一样被定义成一个服务。例如,你有以下简单的控制器:

然后你可以定义它为如下服务:

 

涉及到该服务

去使用一个定义为服务的控制器时,要采用冒号(:)。例如,如何转发到上面定义的 acme.hello.controller的indexAction()方法:

注:当你使用这个语法时,不能够舍弃indexAction方法名的Action部分。

当定义路由_controller的值时,你可以用路由指定服务同样也使用冒号(:)等相同符号:

你还可以采用注释的方式配置路由,来使用一个定义为服务的控制器。请查看 FrameworkExtraBundle documentation

 

替代继承的基础Controller方法

当使用的控制器作为服务时,他可能不会用Controller类。也不依赖于它的快捷方式方法,你会直接与你所需要的服务进行交互。幸运的是,通常我们会很容易的和基础的Controller(一个伟大的代码)来执行许多常见任务。
举个例子,如果你想呈现一个模板,而不是直接创建Response对象,如果你继承了基础的Controller,那么你原来的代码应该这样写:

如果你看一下基础Controller在symfony中render函数的源代码,你会发现这个方法实际使用的是templating服务。

在一个作为服务的控制器中,您可以直接注入模板服务并使用它:

服务定义也需要修改指定构造函数参数:

不是从容器获取templating服务,而是你能够精确的注入需要的服务到你的Controller里。

 

这并不意味着你不能从自己的基础控制器扩展这些控制器。之所以从标准的基本控制器中剥离,是因为控制器的一些方法,使用前提是“有控制器可以使用”但如果控制器“被定义成服务”,此时控制器就不可用。把它从基本的控制器中剥离可能是一个好主意,提取通用的代码到一个服务里,代码再注入到一个基本控制器扩展。这两种方法都是有效的,主要看你想要如何整理你的可重用代码。