这更像是一个“最佳实践”问题而非实际问题:
我正在研究Symfony 2中的一个项目,我已经构建了一个包来处理我的所有web服务。基本上,一个控制器获取一些JSON数据,将其发送到另一个控制器以检查它是否与描述的格式匹配,然后关闭到另一个控制器以处理数据库调用并最终返回到初始控制器以返回JSON响应。
我通过这样的方式在控制器之间发送数据:
$controller = new \Acme\myBundle\Controller\DefaultController;
$response = $controller->function();
这是正常的,但我一直遇到一个问题。在控制器中我将数据传递给我需要实例化AppKernel并调用启动函数以使任何Symfony函数工作。这对我来说似乎有点愚蠢,这让我相信我可能做错了。
赞赏任何建议或提示!
修改/更新 谢谢大家的评论。我已将控制器设置为服务,服务正在运行但我仍需要在从服务内部调用服务时手动启动/实例化内核。
#config.yml
# API Services
services:
service.handler:
class: Acme\APIBundle\Controller\ServicesController
arguments:
container: "@service_container"
service.definitions:
class: Acme\APIBundle\Controller\DefinitionController
arguments:
container: "@service_container"
从另一个bundle控制器中,我可以从这些服务中调用一个函数而没有问题:
$test = $this->get("service.handler")->testFunction();
$test2 = $this->get("service.definitions")->anotherTestFunction();
我遇到的问题是如果我在一个服务中调用一个函数,然后尝试从该服务内部调用另一个服务,我得到以下PHP错误
Fatal error: Call to a member function get() on a non-object in /vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 188
我可以通过使用此函数并调用它而不是使用$ this
来避免该错误 public function bootKernel(){
//boot kernel
$controller = new \Acme\myBundle\Controller\DefaultController;
$kernel = new \AppKernel('dev', true);$kernel->loadClassCache();
$kernel->boot();
$controller->setContainer($kernel->getContainer());
return($controller);
}
我想我的解决方案“有效”,但它似乎并不是一种有效的方法。
编辑2: 如果我把它放在班级的顶部然后修改服务调用它似乎工作...仍然不确定这是否是最好的做事方式。
protected $container;
public function __construct($container) {
$this->container= $container;
}
答案 0 :(得分:10)
我按照上面的controller-as-a-service路线往下走。假设您必须在处理过程中调用3种方法。我们称他们为foo()
,bar()
和something()
。这些方法中的每一种都在不同的控制器中:
namespace Acme\DemoBundle\Controller;
class FooController
{
public function __construct($container, ...)
{
$this->container = $container;
// ... deal with any more arguments etc here
}
public function foo($params)
{
// ...
return $x;
}
protected function get($service)
{
return $this->container->get($service);
}
}
同样适用于bar()
和something()
方法,每个方法都在自己的控制器中。然后,将它们作为服务添加到您的应用程序中。例如,在您的config.yml
(其他可用方法)中:
services:
my.foo.service:
class: Acme\FooBundle\Controller\FooController
arguments:
container: "@service_container"
请参阅more details的Symfony文档,了解如何构造此条目,包括注入任何依赖项,如实体管理器或类似项。现在,您可以从容器中获取此实例:
public function yourMainAction()
{
// ...
$newData = $this->get("my.foo.service")->fooAction($someData);
// ...
return new Response(json_encode($newData), ...);
}
同样适用于BarController
和SomethingController
。现在的优势在于,可以在应用程序中的任何位置(无论是通过上面的容器,还是作为注入的服务)跨服务器提供此服务,而无需自己手动实例化类并提供任何依赖性。
有关容器等的更多信息,Symfony文档上有good section(在上面的链接中引用)。
编辑:调整代码示例以包含将参数传入服务的详细信息。还添加了一个方便的get()
方法来从容器中检索服务。
答案 1 :(得分:1)
我建议将控制器用作service。