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

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

问题描述

这与其说是实际问题,不如说是一个最佳实践"问题:

我正在 Symfony 2 中处理一个项目,并且我已经构建了一个包来处理我的所有网络服务.基本上,一个控制器获取一些 JSON 数据,将其发送到另一个控制器以检查它是否与描述的格式匹配,然后发送到另一个控制器来处理数据库调用,并最终返回到初始控制器以返回 JSON 响应.

我通过执行以下操作在控制器之间发送数据:

$controller = new AcmemyBundleControllerDefaultController;$response = $controller->function();

这工作正常,但我一直遇到一个问题.在控制器中,我将数据传递给我需要实例化 AppKernel 并调用启动函数以使任何 Symfony 函数工作.这对我来说似乎有点愚蠢,这让我相信我可能做错了这一切.

感谢任何建议或提示!

编辑/更新谢谢大家的评论.我已经将我的控制器设置为服务,这些服务正在运行,但是当我从服务内部调用服务时,我仍然需要手动启动/实例化内核.

#config.yml# API 服务服务:服务处理程序:类:AcmeAPIBundleControllerServicesController论据:容器:@service_container"服务定义:类:AcmeAPIBundleControllerDefinitionController论据:容器:@service_container"

从另一个捆绑控制器,我可以毫无问题地从这些服务中的任何一个调用函数:

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

我遇到的问题是,如果我在一个服务内部调用一个函数,然后尝试从该服务内部调用另一个服务,我会收到以下 PHP 错误

致命错误:在第 188 行的/vendor/symfony/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php 中的非对象上调用成员函数 get()

我可以通过使用此函数并调用它而不是使用 $this 来避免该错误

 公共函数 bootKernel(){//引导内核$controller = new AcmemyBundleControllerDefaultController;$kernel = new AppKernel('dev', true);$kernel->loadClassCache();$kernel->boot();$controller->setContainer($kernel->getContainer());返回($控制器);}

我想我的解决方案有效",但它似乎不是一种有效的做事方式.

编辑 2:如果我把它放在班级的顶部,然后修改服务调用它似乎可以工作......仍然不确定这是否是最好的做事方式.

 受保护的 $container;公共函数__construct($容器){$this->container= $container;}

解决方案

我会去controller-as-a-service 路由与上述相同.假设您必须调用 3 个方法作为处理的一部分.我们称它们为 foo()bar()something().这些方法中的每一个都在单独的控制器中:

命名空间 AcmeDemoBundleController;类 FooController{公共函数 __construct($container, ...){$this->container = $container;//... 在这里处理更多的参数等}公共函数 foo($params){//...返回 $x;}受保护的函数 get($service){返回 $this->container->get($service);}}

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

服务:我的.foo.service:类:AcmeFooBundleControllerFooController论据:容器:@service_container"

查看 Symfony 文档以了解 更多关于如何构建此条目的详细信息,包括注入任何依赖项,例如实体管理器或类似项.现在,您可以从容器中获取此实例:

公共函数 yourMainAction(){//...$newData = $this->get("my.foo.service")->fooAction($someData);//...返回新响应(json_encode($newData), ...);}

对于BarControllerSomethingController 也是如此.现在的优势是,该服务可以在您的应用程序中的任何点(无论是通过上述容器,还是作为注入服务)、跨包提供,而无需自己手动实例化类并提供任何依赖项.

有关容器等的更多信息,Symfony 文档有一个 good section 关于它(在上面的链接中引用).

编辑:调整了代码示例以包含将参数传入服务的详细信息.还添加了一个方便的 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 AcmemyBundleControllerDefaultController;
$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: AcmeAPIBundleControllerServicesController
    arguments:
        container: "@service_container"

service.definitions:
    class: AcmeAPIBundleControllerDefinitionController
    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 AcmemyBundleControllerDefaultController; 
    $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 AcmeDemoBundleController;

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: AcmeFooBundleControllerFooController
        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天全站免登陆