【问题标题】:Symfony 2 sharing data between controllersSymfony 2 在控制器之间共享数据
【发布时间】:2014-02-19 09:14:29
【问题描述】:

我已经开始使用 Symfony 2 创建一个项目。我需要在所有控制器之间共享数据。

我添加了一个扩展 symfony\controller 的基本控制器,我的每个控制器都扩展了这个基本控制器

class BaseController extends Controller

class HomeController extends BaseController

此基本控制器将用于分配全局 twig 变量(我知道我可以在配置中执行此操作,但某些变量将从其他配置文件和数据库中获取)。

所以我认为我可以引用容器,因为控制器是容器感知的,但它不是我使用函数的时候(来自构造函数)。

public function __construct ()

我看到人们提到将容器作为参数传递并提到服务,但我看过并无法弄清楚。我想要实现的是:

public function __construct (Container $container) {
    $container->get('twig').addGlobal('foo');
}

【问题讨论】:

    标签: php symfony controller twig


    【解决方案1】:

    这是 Symfony 2 新手的常见绊脚石。控制器/容器问题之前已被问过数百次,因此您并不孤单(提示)。

    为什么你的控制器构造函数代码不起作用?

    首先查看 vendor/symfony...FrameworkBundle/Controller/Controller.php。唔。那里没有构造函数,那么容器到底是从哪里来的?我们看到 Controller 扩展了 ContainerAware。这似乎很有希望。我们查看 ContainerAware(命名空间有助于找到文件所在的位置),再一次,没有构造函数。但是有一个 setContainer 方法,所以我们可以假设容器在构造函数被调用后被注入到控制器中。在基于依赖注入的框架中很常见。

    所以现在我们知道为什么构造函数代码失败了。容器尚未注入。愚蠢的设计对吧?是时候换一个框架了?并不真地。让我们面对现实吧,必须让所有控制器扩展一个基本控制器只是为了设置一些树枝变量并不是最好的设计。

    在控制器动作执行之前,Symfony 执行代码的方法是创建一个控制器事件监听器。它看起来像这样:

    namespace Cerad\Bundle\CoreBundle\EventListener;
    
    use Symfony\Component\DependencyInjection\ContainerAware;
    
    use Symfony\Component\HttpKernel\HttpKernel;
    use Symfony\Component\HttpKernel\KernelEvents;
    use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
    
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class ModelEventListener extends ContainerAware implements EventSubscriberInterface
    {   
        public static function getSubscribedEvents()
        {
            return array(KernelEvents::CONTROLLER => array(
                array('doTwig', 0), // 0 is just the priority
            ));
        }
        public function doTwig(FilterControllerEvent $event)
        {
            // Ignore sub requests
            if (HttpKernel::MASTER_REQUEST != $event->getRequestType()) return;
    
            $this->container->get('twig')->addGlobal('foo');
        }
    }
    // This goes in services.yml
    
    parameters:
        cerad_core__model_event_listener__class: 
            Cerad\Bundle\CoreBundle\EventListener\ModelEventListener
    
    services:
        cerad_core__model_event_listener:
            class:  '%cerad_core__model_event_listener__class%'
            calls:
                - [setContainer, ['@service_container']]
            tags:
                - { name: kernel.event_subscriber }
    

    所以现在我们有了所需的功能,而不需要基本控制器类。

    还要注意,可以通过事件访问控制器。由于已经创建了控制器但尚未调用操作方法,您可以调用控制器方法或将数据直接注入控制器。这很少需要。在大多数情况下,您会向请求对象添加其他信息,然后将其注入控制器的操作方法。

    一旦您对听众和服务感到满意,这确实是一个不错的设计。

    【讨论】:

      【解决方案2】:

      请仔细阅读该问题 - Symfony2 passing data between bundles & controllers,尝试使用其中包含的代码。

      例如,您可以使用service 来解决您的问题。

      【讨论】:

        【解决方案3】:

        如果您查看 Controller 类,您将看到以下内容:

        class Controller extends ContainerAware
        

        这意味着您可以像这样简单地从容器中检索树枝:

        $twig = $this->get('twig');
        

        但我建议你在你的情况下使用custom twig extension。

        【讨论】:

          猜你喜欢
          • 2015-12-15
          • 2014-03-22
          • 1970-01-01
          • 2013-05-28
          • 2016-11-30
          • 1970-01-01
          • 2014-12-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多