Search code examples
phpsymfonysymfony-2.8

How to customize render Symfony


I am a newbie with Symfony 2.8. I have this array

IndexController.php on line 18:
array:6 [▼
  "code" => "Home"
  "parent" => "master"
  "labels" => array:1 [▼
    "en_US" => "Home"
  ]
  "mainMenu" => false
  "footerMenu" => false
  "headerMenu" => true
]

For example: when mainMenu is set to true I need to display mainMenu.html.twig.

With this method I am calling this array

public function indexAction(Request $request, $locale, $page) {
    $pageContent = $this->container->get("pimc_akeneo_cms_page_content_builder");
    $akeneoConnector = $this->container->get("pimc_akeneo_cms_backend_connector");
    $html = $pageContent->build($page, $locale);

    $elements = $akeneoConnector->getCategoryList($page);

    if($elements['mainMenu'] == true){
        $this->render('base/mainMenu.html.twig'); // I have problem in here
    }
    if($elements['headerMenu'] == true){
        $this->render('base/headerMenu.html.twig'); // I have problem in here
    }
    if($elements['footerMenu'] == true){
        $this->render('base/footerMenu.html.twig'); // I have problem in here
    }

    return $this->render('base/index.html.twig', ["content" => $html]);
}

I have headerMenu.html.twig, footerMenu.html.twig and mainMenu.html.twig in base app/Resources/views/base/ . This seems like really an easy problem, but I can't resolve it. So the problem is the syntax to write when for example mainMenu.html.twig is set to true. How can I display this ?


Solution

  • First of all return $this->render() returns HTTP response in the form of Symfony\Component\HttpFoundation\Response instance which is required by every *Action methods in Symfony's controllers. Having that said you cannot return more than one Responses per request and also $this->render() without return doesn't have any impact for Symfony.

    In your case you should move displaying template logic to the View layer like this:

    In your indexAction

    return $this->render('base/index.html.twig', [
        "content" => $html,
        "elements" => $elements // pass this to template
    ]);
    

    In your base/index.html.twig

    {% if elements['mainMenu'] is defined and elements['mainMenu'] is same as(true) %}
        {% include 'base/mainMenu.html.twig' %}
    {% endif %}
    
    {% if elements['headerMenu'] is defined and elements['headerMenu'] is same as(true) %}
        {% include 'base/headerMenu.html.twig' %}
    {% endif %}
    
    etc...
    

    Alternatively (only in case when you have multiple alternative templates possible to be rendered in the same DOM's location):

    {% for tmpl in ['mainMenu', 'headerMenu', 'footerMenu'] %}
        {% if elements[tmpl] is defined and elements[tmpl] is same as(true) %}
         {% include 'base/' ~ tmpl ~ '.html.twig' %}
        {% endif %}
    {% endfor %}
    

    So putting that logic in your templates you keep better MVC separation of concerns and now you don't have to repeat that logic in every Controller which Views has those menus to be rendered. You only have to pass $elements variable then.