2012-02-11 3 views
1

В настоящее время я работаю над приложением 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 от встроенного контроллера. В моем случае вид продолжается частично и полностью отображается как 1 единица, прежде чем он будет вставлен на главную страницу. В этом случае я могу только поместить свой javascript в блок content, что означает, что у меня будут <script> теги в тегах <div>. Я также предпочел бы иметь сценарии в конце тела для производительности пользовательского интерфейса.

Как я могу структурировать свои шаблоны (или это даже возможно), чтобы я мог отображать соответствующие фрагменты из представления встроенного контроллера в соответствующие блоки в шаблоне, который встраивает контроллер? В моем текущем шаблоне библиотека YUI будет загружена после разметки HTML с встроенным контроллером, поэтому доступ к использованию библиотеки YUI внутри встроенного контроллера будет невозможным.

+0

[Duplicate] (http://stackoverflow.com/q/9224347/1146363), хотя его легче читать. Я не думаю, что результаты встроенного контроллера можно разделить на несколько блоков. Возвращаемый результат - это только обработанный html, а не шаблон ветки. Я думаю, вам нужны два встроенных контроллера: один для контента и один для javascript. А в некоторых случаях, возможно, даже для css. – Cerad

+0

Hm. Наличие 2 встроенных контроллеров меньше, чем идея, и не очень элегантное imo. – F21

+0

Ну, на самом деле вам не нужны два контроллера, только два вызова одного и того же контроллера с аргументом, который указывает, что вы хотите, с помощью {'generate': 'html' или 'js' или 'css'}. А затем соответствующим образом настройте свой шаблон. – Cerad

ответ

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 %} 

Я не мог найти способ, чтобы оценить выражение и получить его значение непосредственно в лексемы синтаксического анализатора. По большей части он отлично работает, за исключением этой проблемы.

Если кто-то имеет некоторое представление о том, как получить значение переменного в пределах лексемы синтаксического анализатора, это было бы здорово :)

+0

Я отчаянно ищу решение для аналогичной проблемы: в моем случае я пишу пакет «widget», который способен внедрять несколько контроллеров (что означает, в том числе другие шаблоны), но я хочу иметь возможность «регистрировать», (js/css/less) в правый блок («stylesheets»/«javascripts»). В любом случае, не могли бы вы поделиться своим расширенным кодом Twig? Трудно написать собственный анализатор токенов (нет опыта с ним).Спасибо в пользу. –

0

После одного дня ищет удовлетворяющее решение, я, наконец, выбрать для следующего подход:

  • Render контроллер для функциональности вашего виджета (как вы уже делаете);
  • Рендеринг шаблонов для встраивания активов вашего виджета (контроллеры не нужны и будут тратить ваше время). Игнорировать include, если шаблон не существует.
  • Используйте согласованное соглашение об именах, чтобы сделать функциональность виджета более динамичной.

Пример одного виджета:

{% "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.

альтернативы, на мой взгляд, не имеют многих недостатков:

  • Использование нескольких контроллеров: слишком тяжелы и не нужны, потому что активы не будут нуждаться в любой контроллер.
  • Загрузка элементов виджетов непосредственно на странице: сложно поддерживать при изменении виджетов/активов.
Смежные вопросы