控制器中的全局部分行为

时间:2012-05-18 09:28:20

标签: php templates symfony

我的应用程序中的大多数控制器都有一个基本控制器,如下所示:

class BaseController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
    /**
     * 
     * @Route("/")
     */
    public function indexAction($partial = false)
    {
            $this->partial = $partial;
        $this->currentAction = 'index';

        return $this->r();
    }
}

这附带一组模板,可以是带有布局的完整html页面,也可以只是内容。这是通过模板中的一行完成的:

{% extends this.partial ? "SomeProject:_base:partial.html.twig" : "SomeProject::layout.html.twig" %}

(其中this是控制器参考)。

然后可以在其他控制器中呈现这些模板,而无需通过布局重复布局。

{% render 'SomeProject:SomeController:index' with  { "partial":true }  %}

我对这种方法的问题是:

  1. 每个需要部分控制器的操作都必须有$partial个参数。由于大多数动作都有可能是部分动作,因此所有控制器都必须随附。
  2. 每个可能的部分操作都必须有$this->partial = $partial行,这很容易被遗忘。
  3. 通过使用一些Symfony或Twig魔法(覆盖render标签等)有一种更清洁的方式。为摆脱上述问题?

2 个答案:

答案 0 :(得分:0)

我已经在大多数控制器中覆盖了渲染方法,以便将一些标准变量注入到我的模板中。它似乎运行良好,但它将为您做的一切将是从控制器渲染模板更容易,因为您不必显式地将$ this传递给模板。

我不太确定传递对控制器的引用是个好主意。至少在你的例子中,只是传递部分似乎就是你所需要的。

你真的需要为你的模板提供这种部分功能吗?似乎更容易只有两个模板(一个用于页面,一个用于部分)。但也许你的用例需要它。

答案 1 :(得分:0)

经过一些研究和在内部挖掘后,我提出了一个优雅的解决方案。

答案是构建一个事件监听器(在Symfony2 Docs中)。更确切地说:一个控制器监听器,其中的类似于下面的内容。这允许透明地处理partial而不对Controller代码进行任何更改。

class ControllerListener
{
    /**
     *
     * @param BaseController $ctrl
     * @param Request $request
     * @return BaseController 
     */
    public function injectPartial($ctrl,Request $request)
    {
        if ($ctrl instanceof BaseController)
        {
            if ($request->get("partial",false))
                $ctrl->setPartial($request->get ("partial"));
        }
        return $ctrl;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $ctrl = $event->getController();
        $ctrl[0] = $this->injectPartial($ctrl[0], $event->getRequest());
        $event->setController($ctrl);
    }
}