6

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?

8
  • 2
    What you are trying to do is breaking MVP pattern (you're trying put logic into view layer). My advice is rethink your solution. Maybe if you say more what you want achieve I can say more. Cheers! Commented Jun 4, 2013 at 13:47
  • 1
    Thanks for the reply @Cyprian, I did feel wrong doing this so perhaps there is another way. My view is split into 3 twig templates that extend a layout template: header, sidebar and content. The sidebar will require dynamic data on each page load (some live stats, for example). I need to have the sidebar contain this data no matter what is in the content template. Commented Jun 4, 2013 at 13:52
  • My aim was to code the sidebar, retrieving it's own data from a separate controller, and then everything I code in the future is just the content pages and I don't need to duplicate any code to get the stats for the sidebar. Commented Jun 4, 2013 at 13:55
  • I would json_encode() the array in the response and use a twig extension to decode it in the view: stackoverflow.com/questions/14500698/decoding-json-in-twig Commented Jun 4, 2013 at 14:10
  • 1
    Ok, I understand - and it's all ok. You should create own controller action for the sidebar and include it in your base template as you did. But instead your sidebar action return anything - it should render whole sidebar view in its own template. So, the call: {% render(controller('AppBundle:Test:index')) %} will produce whole sidebar htmlcode. Am I good thinking what you want? If so, I'll provide wider example in an answer. Commented Jun 4, 2013 at 14:11

1 Answer 1

6

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).

Sign up to request clarification or add additional context in comments.

1 Comment

I think I was worrying about too many levels of abstraction, but this seems to be the best course of action. Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.