Php symfony throw exception

Exception Handling

If you liked what you’ve learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

With a Subscription, click any sentence in the script to jump to that part of the video!

We’ve now walked through the «happy» path: we know how a successful request is converted into a response. But what about the unhappy path. Well, our entire application is wrapped in this try-catch block. So, if an exception is thrown from anywhere, this will catch it. The $catch argument is true by default, so we’re not going to hit this finishRequest() line. Nope, if an exception is thrown, this will call $this->handleThrowable() .

And, this an interesting situation. Because no matter what went wrong in your app — like your database is being eaten by robots, or your PHP code has become self-aware and is rewriting itself, ultimately, you need to return a response to the user. even if that’s just a photo of those robots cooking your servers over a slow fire. Somehow, something needs to convert the Exception into a Response . That is the job of handleThrowable() .

Hello kernel.exception Event

Hold Command or Ctrl and click to jump down to this method. What does handleThrowable() do? I know this may come as a shock to you. but it dispatches another event: KernelEvents::EXCEPTION , or kernel.exception .

Move over and refresh the page. Click into the profiler and then into Events. Now, this page did not throw an exception. So this event was not dispatched. But we can click on «Not Called Listeners» to find it. Let’s see. I went right past it: here it is. The kernel.exception event has about 5 listeners.

How the «Welcome to Symfony» Page is Rendered

The most important one is ErrorListener , which we’re going to look at in a few minutes. But check this out: RouterListener — the same class we looked at earlier — also listens to this event. Why? This powers a minor feature in Symfony. but the way that it accomplishes it is a super fun example of how different parts of Symfony work together. Let’s dive in!

Читайте также:  Java blob to image

I’ll hit Shift+Shift to open up our old friend: RouterListener.php . Let’s see. I’m looking for getSubscribedEvents() . There it is: on KernelEvents::EXCEPTION , call onKernelException() with a priority of -64 . which means that it will be called fairly late compared to other listeners.

Find the onKernelException() method. The purpose of this method is to render a nice «Welcome to Symfony» page when you start a brand new project that has no homepage. That’s what this createWelcomeResponse() does: it renders a PHP template. Let’s see that: Shift + Shift to open welcome.html.php . Here it is: «Welcome to Symfony!» with links to the docs and other things. If you start a brand new Symfony 5 project, this is what you would see.

I love this page. because it’s really cute. But for our purposes, I want to know how this works. Back in RouterListener . actually, look back at HttpKernel . Listeners to this event are passed an ExceptionEvent object. and the actual exception that was thrown — that’s the $e variable — is passed into that object! That makes sense: listeners to this event will probably need to know which exception was thrown.

In RouterListener , it checks to see if the exception that was thrown is an instance of NotFoundHttpException . Which, by the way, is the exact exception class that we throw in a controller whenever we want a 404 page. It’s inside the createNotFoundException() method: return new NotFoundHttpException . That’s not important for understanding how this welcome page is rendered. but it is interesting that this exception class keeps popping up.

Anyways, if the exception is not a NotFoundHttpException , this listener does nothing. But if it is, it then checks to see if the previous exception is an instance of NoConfigurationException . If so, it renders the welcome page.

So. then. what’s going on exactly? Here’s the story: when the Router is executed, if no route is matched and the URL is / , it throws a NoConfigurationException .

If you scroll up to onKernelRequest() , remember, this is what executes the router. Specifically, the matchRequest() method throws that exception. The NoConfigurationException extends ResourceNotFoundException . That’s important because this entire block is wrapped in a try-catch: it’s catching ResourceNotFoundException .

So in general, if the router can’t match a route, it throws a ResourceNotFoundException . But in this one special case — when you’re accessing the homepage and no route was found — it throws a subclass called NoConfigurationException .

Читайте также:  min-width

So it catches the exception and throws a new NotFoundHttpException but set the exception from the router as the previous exception. Ultimately, this NotFoundHttpException is thrown from this method, caught by the try-catch in HttpKernel and put into the ExceptionEvent object.

Then, RouterListener listens to the kernel.exception event and if the exception is a NotFoundHttpException whose previous exception is NoConfigurationException . it renders the welcome page.

Manually Rendering the Welcome Page

For fun, let’s see if we can trigger the welcome page manually. Go to ArticleController . We’re throwing a NotFoundHttpException if the slug wasn’t found in the database. Pass null as the first argument to createNotFoundException() — that’s just the message, not important for us. The second argument is a way to set the previous exception. Let’s fake what the router does: new NoConfigurationException() .

Источник

Основы Symfony 3 и не только

Немаловероятно, что в процессе прохождения длинного пути от запроса до ответа будут появляться какие-либо ошибки. По-умолчанию Symfony ловитя любые исключения и пытается найти соответствующий ответ для них. В методе handle() класса HttpKernel вся обработка запроса обёрнут в блок try/catch:

// \Symfony\Component\HttpKernel\HttpKernel.php . try < return $this->handleRaw($request, $type); > catch (\Exception $e) < if (false === $catch) < $this->finishRequest($request, $type); throw $e; > return $this->handleException($e, $request, $type); > … 

Если $catch установлена в true, то в случае выявления ошибки вызывается метод handleException(). Этот метод вызывает событие KarnelEvents::EXCEPTION (kernel.exception), которому передаётся объект GetResponseForExceptionEvent.

// \Symfony\Component\HttpKernel\HttpKernel.php private function handleException(\Exception $e, $request, $type) < $event = new GetResponseForExceptionEvent($this, $request, $type, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); // a listener might have replaced the exception $e = $event->getException(); if (!$event->hasResponse()) < $this->finishRequest($request, $type); throw $e; > $response = $event->getResponse(); . > 

Возможно 2 варианта:

  1. Один из слушателей данного события установил надлежащий объект Response для специфичного исключения и заменил оригинальный объект Exception ($e). В данном случае HttpKernel проверяет новый объект Response для установки правильного статус-кода ответа. Если мы не установили свой код, то по-умолчанию будет отдаваться “500 — Internal server error”.
  2. Если ни один слушатель не вызвал метод setResponse(), исключение будет выброшено повторно, но уже без автометической обработкой Symfony. В том случае если в настройках PHP включена директива display_errors — PHP выведет ошибку “как есть”.

Источник

Оцените статью