Jimbo
Jimbo

Reputation: 26523

Symfony2 - Twig render controller and return array response

Note: What I'm doing here is embedding controllers <--- see that link for a similar (official) example.

I want to call a controller from a twig template, and have that controller return an array that I can then use throughout the rest of my template.

I can do this with individual variables:

Twig

{% set testVar = render(controller('AppBundle:Test:index')) %}

Controller

class TestController extends Controller
{
    public function testAction()
    {
        return new Response('OH HAI');
    }
}

However, the following throws an exception: ("The Response content must be a string or object implementing __toString(), "array" given.") with the same twig file.

public function testAction()
{
    return new Response(array('test' => 1, 'foo' => 'bar'));
}

This throws the above exception. How can I accomplish that which I seek without creating a dummy, useless extra template for the controller to render?

Upvotes: 6

Views: 24379

Answers (1)

Cyprian
Cyprian

Reputation: 11364

The standard way to achieve what you want looks something like that.

Lets assume that you have your regular action. Eg.

class TestController extends Controller
{
    public function testAction()
    {
        return $this->render('AppBundle:Test:index.html.twig');
    }
}

And the template:

<html>
    <body>
        {% block sidebar %}
            {{ controller('AppBundle:Test:sidebar') }}
        {% endblock %}
        {% block content %}
            Hello world
        {% endblock %}                    
    </body>
</html>

Next you need create some action for the sidebar. Note that in this way you avoid put any logic into your view layer.

class BaseController extends Controller
{
    public function sidebarAction()
    {
        $status = $this->get('some.status.logic')->retrieveStatus();

        return $this->render('AppBundle:Base:sidebar.html.twig', array(
            'status' => $status,
        ));
    }
}

And your Base/sidebar.html.twig:

<div class="sidebar">
   {{ status.showStatusInfo() }}
</div>

And that's all. You're not breaking MVP in that way, because you still don't have any logic in your view layer (the logic for the sidebar is in BaseController).

Upvotes: 6

Related Questions