Creating a widget manager on top of Symfony 2 (multiple controllers on the same page)

Use case
I am developing CMF on top of Symfony2. One of the features will be support for "widgets": the ability for end users to add small "blocks" or "modules" to the page. Examples:

  • Small login form
  • Grocery list
  • Some photos from the gallery
  • Basket

The idea is that most of these widgets will reference regular full-featured Routes / Controllers.

For example: the user needs a list of popular products in the sidebar on the content page. Elements will refer to the normal / product / {name} route in the ProductController. But the list in this case will be a widget. The end user can determine where it should be placed, and, for example, how many elements should be shown.

The behavior of "widgets" is the same as regular Symfony2 controllers, it has routes, actions, displays a view, etc. There is a WidgetManager with full access to download widgets, customize and render them in the right place.

I don't have much experience with Symfony2, but I have been playing with it for over 3 months now. I definitely want to stay with Symfony2, but you will need to add magic to implement some of my ideas.

Question
What is the best way to support rendering of multiple controllers (widgets) in a single request?

Study
Symfony TwigExtension "ActionExtension" contains a "rendering" method that contains the main idea:

<div id="sidebar"> {% render "AcmeArticleBundle:Article:recentArticles" with {'max': 3} %} </div> 

(Documentation: http://symfony.com/doc/current/book/templating.html#embedding-controllers )

But it is very limited. Some problems with this approach:

  • I can’t configure the "widgets" before rendering them (for example: $myWidget->set('show_toolbar', false) ), I don’t want to pass all the parameters as parameters of the controller action.
  • Cannot use template inheritance. I need this, for example, to "inject" resource references (javascript / css) into the <HEAD> base block.

What I want

I want the following code to work (this is a simplified example):

 // Serius\PageBundle\Controller\PageController.php // executed by a catch-all route public function indexAction($url) { // load CMS page, etc $widgets = $this->loadWidgets($page); // widgets configuration is stored in database // at this point, $widgets is an array of Controller *instances* // meaning, they are already constructed and configured return $this->render("SeriusPageBundle:Page:content.html.twig", array( 'widgets' => $widgets )); } 

Serius \ PageBundle \ Resources \ view \ Page \ content.html.twig

 {% extends 'SeriusPageBundle::layout.html.twig' %} {% block content %} {% for widget in widgets %} <div> {% render widget %} <!-- Of course, this doesn't work, I would have to create my own Twig extension --> </div> {% endfor %} {% endblock %} 

Example widget template:

 {% extends '::base.html.twig' %} {% block stylesheets %} My stylesheets {% endblock %} {% block body %} This is a shoppingcart widget! {% endblock %} 

How can i achieve this? Does anyone have any experience with this? I already looked at the Symfony CMF project, but it does not support this (as far as I could find out).

+4
source share
2 answers

I have something similar, and I think this code will help you. In the selected template, you get variables with block names.

 public function render() { $modules = $this->moduleService->getModules(); foreach($modules as $m){ $templateName = $m->getTemplateName(); $template = $this->twig->loadTemplate($templateName); $blockNames = $template->getBlockNames(); foreach($blockNames as $b){ if(isset($this->blocks[$b]) == false) $this->blocks[$b] = ''; $this->blocks[$b] .= $template->renderBlock($b, array('a' => 'aaa', 'b' => 'bbb')); } } $content = $this->twig->render('Admin/index.html.twig',$this->blocks); return new \Symfony\Component\HttpFoundation\Response($content); } 
+1
source

I know this is old, but if someone is looking for something like this, SonataBlockBundle may be your solution.

https://github.com/sonata-project/SonataBlockBundle

+1
source

All Articles