嵌入式控制器视图与资产

时间:2012-02-11 07:51:48

标签: templates symfony

我目前正在研究symfony2应用程序并使用嵌入式控制器。我的嵌入式控制器就像小部件一样,它应该封装它自己的一组功能,并且可以嵌入到任何地方并且仍然可以运行。

我有一个名为在线用户的控制器。它生成的视图很简单,只是一个在线用户列表。但是,我想在该视图中添加一些javascript,以便我可以使用ajax来检索被点击的用户的信息。

控制器基本上返回一个视图:

return $this->render('AppBundle:Users:usersOnline.html.twig', array('somedata' => $data);

以下是该控制器的视图:

{% extends partial.html.twig" %}
{%  block content %}
 <ul>
   <li><a href="site.com/ajax/user/1">User 1</a></li> (this would all be generated using 'somedata')
   <li><a href="site.com/ajax/user/2">User 2</a></li>
   ....
 <ul>
{% endblock content %}
{%  block scripts %}
   ..some javascript for interacting with this widget
{% endblock %}

这是从以下部分延伸的部分:

{%  block content %}
{% endblock content %}

{%  block scripts %}{% endblock %}

这是嵌入控制器的主页面:

{% "base.html.twig" %}
{% block title %}Main{% endblock %}

{% block content %}
 ..some markup here
 <div id="usersonline">
  {% render "AppBundle:Users:usersOnline" with {'max': 4} %}
 </div>
{% endblock %}

{% block scripts %}
  ..some javascript
{% endblock %}

这是它扩展的基础:

<!DOCTYPE html>
<html>
    <head>
     <meta charset="utf-8">
     <title>{% block title %}{% endblock %} - App</title>       
     ...Some stylesheets
    </head>
    <body>
        {% block content %}{% endblock %}
        <script src="http://yui.yahooapis.com/3.5.0pr2/build/yui/yui-min.js"></script>
        {%  block scripts %}{% endblock %}
    </body>
</html>

我现在面临的问题是包含来自嵌入式控制器的javascripts。在我的例子中,视图扩展为partial,并在插入主页面之前完全呈现为1个单元。在这种情况下,我只能将我的javascript放在content块中,这意味着我会在<script>个标记中包含<div>个标记。我还希望在正文末尾有脚本来实现用户界面性能。

我应该如何构建我的模板(或者甚至是可能的),以便我可以将嵌入式控制器视图中的相应部分渲染到嵌入控制器的模板中的适当块中?在我当前的模板中,YUI库将在嵌入式控制器呈现的HTML标记之后加载,因此使用嵌入式控制器中的YUI库进行访问是不可能的。

2 个答案:

答案 0 :(得分:0)

我编写了一个扩展程序,它本质上是一个处理此问题的令牌解析器。令牌解析器的文档非常稀疏,代码也大部分都没有注释,所以需要花点时间才能开始工作。

我已经构建了解析器,所以在开始时,你会声明一些东西(类似于{% use %}):

{% myparser "AppBundle:Users:usersOnline" with {'max': 4} as xyz %}

然后可以使用xyzcontent之类的块,然后使用{{block('xyzcontent')}}将它们渲染到适当的位置。它运作得很好。但是以下方法不起作用:

{% set max = 4 %}
{% myparser "AppBundle:Users:usersOnline" with {'max': max} as xyz %}

我找不到一种方法来评估表达式并直接在令牌解析器中获取它的值。除了这个问题,大多数情况下它都能正常工作。

如果有人知道如何在令牌解析器中获取变量的值,那就太好了:)

答案 1 :(得分:0)

在寻找满意的解决方案一天后,我最终选择了以下方法:

  • 为您的小部件的功能呈现控制器(就像您已经在做的那样);
  • 渲染模板以嵌入窗口小部件的资源(不需要控制器并且会浪费您的性能)。如果模板不存在,则忽略包含。
  • 使用一致的命名约定,使窗口小部件功能更具动态性。

一个小部件的示例:

{% "base.html.twig" %}
{% block title %}Main{% endblock %}

{% block content %}
 ..some markup here
 <div id="usersonline">
  {{ render(controller("AppBundle:Users:usersOnline", {'max': 4})) }}
 </div>
{% endblock %}

{% block scripts %}
  {{ include("AppBundle:Users:usersOnline_js.html.twig" ignore missing }}
{% endblock %}

{% block stylesheets %}
  {{ include("AppBundle:Users:usersOnline_css.html.twig" ignore missing }}
{% endblock %}

(如您所见,我使用Symfony 2.2的包含和嵌入方式)

或者,一种更动态的小部件呈现方式:

{% "base.html.twig" %}
{% block title %}Main{% endblock %}

{% block widgets %}
 ..some markup here
  {% for widget in widgets %}
    {{ render(controller(widget.controller ~ ':widget', widget.options)) }}
  {% endfor %}
{% endblock %}

{% block scripts %}
  {% for widget in widgets %}
    {{ include(widget.controller ~ ':widget_js.html.twig' ignore missing }}
  {% endfor %}
{% endblock %}

{% block stylesheets %}
  {% for widget in widgets %}
    {{ include(widget.controller ~ ':widget_css.html.twig' ignore missing }}
  {% endfor %}
{% endblock %}

我的结论

在一个页面中渲染多个控制器,而“合并”它的模板块,在Symfony2中无法实现。 Symfony2一直专注于每个请求的一个控制器,这解释了为什么多个控制器输出是分开的并且难以组合。

我认为Symfony CMF已经(或将会)有一个适当的解决方案,因为整个小部件主题更适用于动态内容托管网站。

无论如何,我认为我的方法是将嵌入式控制器和包含的模板结合起来是迄今为止Symfony 2的最佳方法。

在我看来,替代品确实有许多缺点:

  • 使用多个控制器:太重而且不需要,因为资产不需要任何控制器。
  • 直接在页面中加载小部件资产:更改小部件/资产时难以维护。