2
votes

what I am trying to do is to have custom error page, not only will they be extending the base layout but also I want extra up selling content in those pages too so changing templates only is not an option

regardless of the reason (404 Not Found or just missing variable) I would like to show my template and my content instead

I have spent hours trying to get this going with no luck

app/console --version
Symfony version 2.5.6 - app/dev/debug

I tried some resources, but couldn't get it working. The name a few:

http://symfony.com/doc/current/reference/configuration/twig.html http://symfony.com/doc/current/cookbook/controller/error_pages.html

I'm running in dev with no debug, see app_dev.php below:

$kernel = new AppKernel('dev', false);

following the tutorials i got these extra bits

app/config/config.yml

twig:
    exception_controller:  SomethingAppBundle:Exception:show

in my bundle

<?php

namespace Something\AppBundle\Controller;

use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class ExceptionController extends Controller
{
    public function showAction( FlattenException $error, DebugLoggerInterface $debug)
    {
        print_r($error);
    }

}

but my error controller does not get executed,

I am on purpose causing error by trying to echo undefined variable in different controller, since it should handle error from entire application

1
"some useless resources I tried, in fact I tried many more but from the frustration I am only going to mention these two, after all its the "documentation" right, despite nothing ever worked from there, hate to be bragging but WTFPOS Documentation". I know you're frustrated, but please don't blame others for it. If this is your honest opinion, please show me code examples that aren't working for you and we'll fix them. Just like we did for all other doc bugs in the past 3 yearsWouter J
sorry, but the code above should have worked for "Replacing the Default ExceptionController" sectiontomhre
@tomhre Did you solve this problem?Paweł Kolanowski

1 Answers

2
votes

At the beginning you need to create action in the controller:

<?php
namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;

class ErrorController extends Controller
{
    
    public function notFoundAction()
    {
        return $this->render('error/404.html.twig');
    }
}

Then you need to create a Listener:

<?php
namespace AppBundle\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\HttpKernelInterface;

class NotFoundHttpExceptionListener
{
    private $controller_resolver;
    private $request_stack;
    private $http_kernel;

    public function __construct($controller_resolver, $request_stack, $http_kernel)
    {
        $this->controller_resolver = $controller_resolver;
        $this->request_stack = $request_stack;
        $this->http_kernel = $http_kernel;
    }
    public function onKernelException(GetResponseForExceptionEvent $event)
    {

        if ($event->getException() instanceof NotFoundHttpException) {

            $request = new \Symfony\Component\HttpFoundation\Request();
            $request->attributes->set('_controller', 'AppBundle:Error:notFound');
            $controller = $this->controller_resolver->getController($request);

            $path['_controller'] = $controller;
            $subRequest = $this->request_stack->getCurrentRequest()->duplicate(array(), null, $path);

            $event->setResponse($this->http_kernel->handle($subRequest, HttpKernelInterface::MASTER_REQUEST)); // Simulating "forward" in order to preserve the "Not Found URL"

        }
    }
}

Now register the service:

#AppBundle/Resources/config/services.yml
services:
    kernel.listener.notFoundHttpException:
            class: AppBundle\EventListener\NotFoundHttpExceptionListener
            tags:
                - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: -10 }
            arguments: [ @controller_resolver, @request_stack, @http_kernel ]

Not tested this, but rather it should work;)

EDIT:

Tested, it works. On the rendered page, you have a session, so you have access to app.user, his cart, and other matters related to the session.