Symfony2在数据包之间传递数据控制器 [英] Symfony2 passing data between bundles & controllers

查看:250
本文介绍了Symfony2在数据包之间传递数据控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个最佳实践问题,而不是一个实际的问题:



我在Symfony 2的项目上工作,以处理我的所有Web服务。基本上,一个控制器接收一些JSON数据,将其发送到另一个控制器以检查它是否与所描述的格式匹配,然后关闭到另一个控制器以处理数据库调用,并最终返回到初始控制器以返回JSON响应。



我在控制器之间发送数据的操作如下:

  $ controller = new \Acme\myBundle\Controller\DefaultController; 
$ response = $ controller-> function();

这样工作正常,但我遇到了一个问题。在控制器中我传递数据到我需要实例化AppKernel和调用任何Symfony函数的启动功能工作。这对我来说似乎有点愚蠢,这导致我相信我可能做这个错了。



任何建议或提示赞赏!



EDIT / UPDATE
谢谢大家的意见。我已经设置我的控制器作为服务,服务是工作,但是我仍然需要手动引导/实例化内核,当我从服务内部调用服务。

 #config.yml 
#API服务
服务:
service.handler:
class:Acme\APIBundle\Controller\ServicesController
arguments:
container:@service_container

service.definitions:
class:Acme \APIBundle\Controller\DefinitionController
arguments:
container:@service_container


$ b b

从另一个bundle控制器,我可以从这些服务中调用一个函数没有问题:

  $ test = $ this-> get(service.handler) - > testFunction(); 
$ test2 = $ this-> get(service.definitions) - > anotherTestFunction();

我有一个问题是如果我调用一个服务中的函数,然后尝试调用服务内部的另一个服务我得到以下PHP错误

 致命错误:调用成员函数get -object in /vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php on line 188 

我可以通过使用这个函数并调用它而不是使用$ this

  public function bootKernel 
//引导内核
$ 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;
}


解决方案

控制器即服务路由与上述。说你必须调用3种方法作为处理的一部分。让我们把它们叫做 foo() bar() something $ c>。这些方法都在单独的控制器中:

 命名空间Acme\DemoBundle\Controller; 

class FooController
{
public function __construct($ container,...)
{
$ this-> container = $ container;
// ...在这里处理任何更多的参数等等。
}

public function foo($ params)
{
// ...
return $ x;
}

protected function get($ service)
{
return $ this-> container-> get($ service);
}
}

同上 something()方法,每个都在自己的控制器中。然后,将它们作为服务添加到您的应用程序。例如在 config.yml (可用的其他方法):

 
my.foo.service:
class:Acme\FooBundle\Controller\FooController
arguments:
container:@service_container

查看Symfony文档,包括注入任何依赖项,如实体管理器或类似的。现在,您可以从容器中获取此实例:

  public function yourMainAction()
{
// ...

$ newData = $ this-> get(my.foo.service) - > fooAction($ someData);

// ...

返回新的响应(json_encode($ newData),...);
}

同样, BarController SomethingController 。现在的优势是,此服务可以在应用程序中的任何点(无论是通过如上所述的容器,还是作为注入服务)在捆绑中提供,而无需自己手动实例化类并提供任何依赖。 p>

有关容器等的详细信息,Symfony文档有一个 (在上面的链接中引用)。



编辑:调整代码示例以包含传入的详细信息参数到服务。还添加了方便从容器中检索服务的 get()方法。


this is more of a 'best practice' question than an actual problem:

I'm working on a project in Symfony 2 and I've built a bundle to handle all of my webservices. Basically one controller takes some JSON data, sends it off to another controller to check it matches a described format, then off to another controller to handle the database calls and eventually back to the initial controller to return a JSON response.

I'm sending data between controllers by doing something like this:

$controller = new \Acme\myBundle\Controller\DefaultController;
$response = $controller->function();

This works correctly, but I keep coming across one problem. In the controller I pass data to I need to instantiate AppKernel and call the boot function for any Symfony function to work. This to me seems a little bit silly which leads me to believe I may be doing this all wrong.

Any suggestions or tips appreciated!

EDIT/UPDATE Thank you all for the comments. I have set up my controllers as services, the services are working but I am still needing to manually boot/instantiate the kernel when I call a service from inside a service.

#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"

From another bundles controller I can then call a function from either of those services without problem:

 $test = $this->get("service.handler")->testFunction();
 $test2 = $this->get("service.definitions")->anotherTestFunction();

Where I DO have a problem is if I call a function inside of one service, then try to call another service from inside that service I get the following PHP error

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

I can avoid that error by using this function and calling it rather than using $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);    
}

I guess my solution 'works' but it certainly doesn't seem an efficient way to do things.

EDIT 2: If I stick this at the top of the class then modify the service call it seems to work... Still not sure if this is the best way to do things.

    protected $container;

public function __construct($container) {
    $this->container= $container;
}

解决方案

I'd go down the controller-as-a-service route with the above. Say you have to call 3 methods as part of your processing. Let's call them foo(), bar() and something(). Each of these methods are in separate controllers:

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);
    }
}

Ditto for the bar() and something() methods, each in their own controller. Then, add them to your application as a service. Eg in your config.yml (other methods available):

services:
    my.foo.service:
        class: Acme\FooBundle\Controller\FooController
        arguments:
            container: "@service_container"

See the Symfony docs for more details about how you can construct this entry, including injecting any dependencies such as an entity manager or similar. Now, you can get an instance of this from the container:

public function yourMainAction()
{
    // ...

    $newData = $this->get("my.foo.service")->fooAction($someData);

    // ...

    return new Response(json_encode($newData), ...);
}

Likewise again for BarController and SomethingController. The advantage now is that this service can be made available at any point in your application (whether via the container as above, or as an injected service), across bundles, without needing to instantiate the class manually yourself and provide any dependencies.

For more information about the container etc, the Symfony docs have a good section on it (referenced in the link above).

Edit: Adjusted the code example to include details of passing in arguments into the service. Also added a convenience get() method to retrieve services from the container.

这篇关于Symfony2在数据包之间传递数据控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆