1
votes

I've made it simpler (apologies for the complicated question which I've left at the bottom).

I want to have a twig template render another controller as a sub-part.

Here's the parent twig (Resources/views/Default/testRenderParent.html.twig):

<p>Look! I am your father!</p>
<p>But look, I am not your
{{ render(controller("SarelTestBundle:Default:testRenderChild")) }}</p>

Here's the child twig (Resources/views/Default/testRenderChild.html.twig):

KID

The controller (Controller/DefaultController.php):

<?php
namespace Sarel\Test\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

/**
 * @Template()
 **/
class DefaultController extends Controller
{
    /**
     * @Route("/testRenderParent")
     */
    public function testRenderParentAction()
    {
        return array();
    }

    /**
     * @Route("/testRenderChild")
     */
    public function testRenderChildAction() {
        return array();
    }
}

When you run this, with the following URL /testRenderChild you should get "KID" echoed. When you run this, with the URL /testRenderParent (notice the "Parent" part), you should get echoed:

Look! I am your father!
But look, I am your KID

However, instead you get this echoed, and the error below it:

Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
Look! I am your father!
But look, I am not your
FatalErrorException: Error: Maximum function nesting level of '250' reached, aborting! in /Users/sarel/www/playpen/app/cache/dev/classes.php line 6134

Thus you can see, it's rendering "Look! I am your father! But look, I am your "... and then instead of rendering the child controller with it's twig template, it re-renders the parent, ending in an endless loop, which is arrested by the exception.

--- copy before I changed it ---
--- copy before I changed it ---
--- copy before I changed it ---

So I'm trying to embed a controller (and ultimately the template that the action renders) in my symfony2 project using the guidelines in enter link description here.

My Controller is defined below:

<?php
namespace OTS\CoreBundle\Controller;

/**
 * @Template()
 */
class EmergencyContactsController extends Controller
{
    public function addEmergencyContactAction(Request $request, $id) {
        return array();
    }
}

I have a twig template attached to that, which right now just have "hello world" in the form of a twig file called addEmergencyContact.html.twig.

When I go to the URL for this, which is something like localhost/my_route_to_it it works perfectly fine and I see "hello world" on the screen.

Now, according to this I merely have to put the following twig command in:

{{ render(controller('OTSCoreBundle:EmergencyContacts:addEmergencyContact', {'id': 15})) }}

When I do this and I load the holding-route it appears to be trying to load the main route, and then load the main route again inside the spot where I render the child-route. I know this because it's telling me there's variables missing - variables that I'm only using in the main twig file.

Yet, when I:

  1. Don't have the {{ render... }} in there, it works fine - i.e. it's not other code that's giving me the exception of missing variable
  2. Render only the child-route I get a nice "hello world" back - i.e. it's not the child twig or child controller that's buggy
2
It is a bit unclear what your problem is...cheesemacfly
@cheesemacfly sorry I've clarified it, and I have also solved it after putting together a nice sandbox for it. It was the @Template() which was associated with the controller and not the actions individually which SensioFrameworkExtraBundle provides.Sarel

2 Answers

2
votes

Hmmm. The question is a bit confusing but:

A. Like all controller actions, your addEmergencyContact needs to return a response, not an array. So:

class EmergencyContactsController extends Controller
{
    public function addEmergencyContactAction(Request $request, $id) 
    {
        $tplData = array();
        $tplData['id'] = $id;
        return $this->render('CoreBundle::emergency_contact.html.twig', $tplData);
    }
}

B. You need two template files. Something like:

class HelloWorldController extends Controller
{
    public function helloWorldAction(Request $request, $id) 
    {
        $tplData = array();
        $tplData['id'] = $id;
        return $this->render('CoreBundle::hello_world.html.twig', $tplData);
    }
}

C. The render line then goes in the hello_world.html.twig file.

{{ render(controller('OTSCoreBundle:EmergencyContacts:addEmergencyContact', {'id': 15})) }}

D. Note that your emergency_contact template will only have access to values passed into it by the emergency contact action. It will not "inherit" the values that hello_world has.

So why is my code formatting messed up? Did not like numbered lists.

2
votes

This turns out to be a bug in the way annotations work. When I change the controller from being globally @Template() enabled to moving that old-school back to each action individually, it works. Here's the updated controller, look at where the @Template() now sits:

<?php
namespace Sarel\Test\TestBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class DefaultController extends Controller
{
    /**
     * @Route("/testRenderParent")
     * @Template()
     */
    public function testRenderParentAction()
    {
        return array();
    }

    /**
     * @Route("/testRenderChild")
     * @Template()
     */
    public function testRenderChildAction() {
        return array();
    }
}