Search code examples
phpsymfonysonata-adminsonata

Render view using response object


I am working on a project in symfony 3 and I have the following code which returns an instance of Response

public function dashboardAction()
{
    return parent::dashboardAction();
}

The parent method of the above code is:

public function dashboardAction()
{
    $blocks = [
        'top' => [],
        'left' => [],
        'center' => [],
        'right' => [],
        'bottom' => [],
    ];

    foreach ($this->container->getParameter('sonata.admin.configuration.dashboard_blocks') as $block) {
        $blocks[$block['position']][] = $block;
    }

    $parameters = [
        'base_template' => $this->getBaseTemplate(),
        'admin_pool' => $this->container->get('sonata.admin.pool'),
        'blocks' => $blocks,
    ];

    if (!$this->getCurrentRequest()->isXmlHttpRequest()) {
        $parameters['breadcrumbs_builder'] = $this->get('sonata.admin.breadcrumbs_builder');
    }

    return $this->render($this->getAdminPool()->getTemplate('dashboard'), $parameters);
}

I would like to pass a variable articles to the view in the instance of the Response.

I tried doing something like this

return $this->render(parent::dashboardAction(), array(
        'articles' => $articles,
    ));

But it does not work. Any help ?


Solution

  • $this->render returns a Response object and the first parameter is the name of a template to render (a string). You are trying to pass the Response object as first parameter to render again, which obviously can't work.

    Also $this->render literally renders the template with the parameters provided. That means the return value of your parent dashboardAction returns a response object containing the rendered HTML of the template returned by $this->getAdminPool()->getTemplate('dashboard'). There is no way you can change the rendered HTML at that point if you don't want to actually work with the completely rendered HTML (no, you don't want to).

    In general I don't think it is a good idea to reuse action methods directly. Instead you can do the following:

    Create a method getDashboardParameters in your parent class, which only returns the parameters for the render function, but does not call render.

    protected function getDashboardParameters()
    {
        $blocks = [
            'top' => [],
            'left' => [],
            'center' => [],
            'right' => [],
            'bottom' => [],
        ];
    
        foreach ($this->container->getParameter('sonata.admin.configuration.dashboard_blocks') as $block) {
            $blocks[$block['position']][] = $block;
        }
    
        $parameters = [
            'base_template' => $this->getBaseTemplate(),
            'admin_pool' => $this->container->get('sonata.admin.pool'),
            'blocks' => $blocks,
        ];
    
        if (!$this->getCurrentRequest()->isXmlHttpRequest()) {
            $parameters['breadcrumbs_builder'] = $this->get('sonata.admin.breadcrumbs_builder');
        }
    
        return $parameters;
    }
    

    Change your parent dashboardAction to look like this:

    public function dashboardAction() {
        return $this->render($this->getAdminPool()->getTemplate('dashboard'), $this->getDashboardParameters());
    }
    

    Change your child dashboardAction to look like this:

    public function dashboardAction() {
        $parameters = $this->getDashboardParameters();
        $parameters['articles'] = $articles;
        return $this->render($this->getAdminPool()->getTemplate('dashboard'), $parameters);
    }