WEBVTT NOTE Created by CaptionSync from Automatic Sync Technologies www.automaticsync.com 00:00:00.066 --> 00:00:03.646 align:middle After the kernel.request event is dispatched, 00:00:03.866 --> 00:00:08.786 align:middle it checks if $event->hasResponse() and, if that's true... 00:00:09.046 --> 00:00:11.346 align:middle it returns the response! 00:00:11.846 --> 00:00:18.646 align:middle Well, it calls $this->filterResponse() and returns that - but that's not too important. 00:00:18.956 --> 00:00:20.026 align:middle We'll see that method later. 00:00:20.816 --> 00:00:23.456 align:middle The point is: the function ends. 00:00:24.026 --> 00:00:30.406 align:middle The response is returned immediately before our controller is executed or anything else. 00:00:31.276 --> 00:00:32.346 align:middle This is kinda cool. 00:00:32.796 --> 00:00:39.406 align:middle If a listener to kernel.request somehow already has enough information to return a response... 00:00:39.706 --> 00:00:40.536 align:middle it can do that! 00:00:41.176 --> 00:00:45.746 align:middle It's not super common, it could be used for security or a maintenance page... 00:00:46.056 --> 00:00:48.056 align:middle but hey! Let's try it ourselves! 00:00:49.116 --> 00:00:55.766 align:middle In src/EventListener/UserAgentSubscriber.php, we can say $event->setResponse(). 00:00:56.716 --> 00:01:02.096 align:middle Not all event classes have this setResponse() method - but RequestEvent does. 00:01:02.746 --> 00:01:08.596 align:middle Then say new Response() and set a very important message. 00:01:10.006 --> 00:01:11.496 align:middle Now when we refresh... 00:01:12.286 --> 00:01:15.476 align:middle yay! Nedry killed every page! 00:01:16.216 --> 00:01:17.196 align:middle Remove that code... 00:01:17.956 --> 00:01:20.006 align:middle and then I'll close a few files. 00:01:21.906 --> 00:01:25.996 align:middle Back in HttpKernel, so far we've dispatch one event. 00:01:26.646 --> 00:01:31.386 align:middle RouterListener listened to that event and modified the request attributes. 00:01:32.096 --> 00:01:33.596 align:middle Let's keep following the code. 00:01:34.616 --> 00:01:39.236 align:middle This next line is interesting: inside the if we have: 00:01:39.236 --> 00:01:44.476 align:middle $controller = $this->resolver->getController(). 00:01:45.546 --> 00:01:49.316 align:middle This "resolver" thing is a "controller resolver". 00:01:49.946 --> 00:01:52.456 align:middle At a high level, it's beautiful. 00:01:53.176 --> 00:01:59.466 align:middle We know that we will eventually need to execute a controller that will create the Response. 00:02:00.276 --> 00:02:05.556 align:middle This class is entirely responsible for determining that controller: 00:02:05.946 --> 00:02:13.776 align:middle we pass it the request and - somehow - it gives us back a controller, which can be any callable. 00:02:14.856 --> 00:02:18.496 align:middle How can we figure out what class $this->resolver is? 00:02:19.056 --> 00:02:25.596 align:middle Well... of course, there's always the handy dd($this->resolver), which... 00:02:25.876 --> 00:02:30.256 align:middle tells us that this is an instance of TraceableControllerResolver. 00:02:31.046 --> 00:02:34.616 align:middle By the way, whenever you see a class called "Traceable" something, 00:02:34.946 --> 00:02:41.216 align:middle this is almost definitely an object that is decorating the real object 00:02:41.346 --> 00:02:45.916 align:middle in the dev environment in order to give us some debugging info. 00:02:46.886 --> 00:02:49.146 align:middle The real controller resolver is inside: 00:02:49.516 --> 00:02:54.506 align:middle Symfony\Bundle\FrameworkBundle\Controller ControllerResolver. 00:02:55.436 --> 00:03:00.836 align:middle Another way to figure this out - maybe a slightly nerdier way for a deep-dive course - 00:03:01.286 --> 00:03:04.546 align:middle is with smart use of the debug:container command. 00:03:05.376 --> 00:03:10.486 align:middle The $resolver is one of the arguments to the constructor on top: it's argument 2. 00:03:11.286 --> 00:03:14.766 align:middle We can see the interface type-hint, but not the concrete class. 00:03:15.516 --> 00:03:18.256 align:middle Scroll back down, then move over to your terminal 00:03:18.386 --> 00:03:26.686 align:middle and run php bin/console debug:container http_kernel - that's the service id 00:03:26.686 --> 00:03:29.586 align:middle of HttpKernel - -- show-arguments. 00:03:31.306 --> 00:03:36.056 align:middle This tells me that the second argument is debug.controller_resolver. 00:03:36.926 --> 00:03:41.766 align:middle Ok, let's run this command again to get more info about that: 00:03:42.906 --> 00:03:48.826 align:middle This uses Symfony's service decoration - a topic we'll see in our next deep-dive tutorial. 00:03:49.386 --> 00:03:53.426 align:middle But basically, when a service is decorated, the original, 00:03:53.806 --> 00:03:59.446 align:middle "inner" service's id will be debug.controller_resolver.inner. 00:03:59.446 --> 00:04:02.546 align:middle So... run debug:container with that! 00:04:05.176 --> 00:04:09.776 align:middle And here it is: the true controller resolver class is... 00:04:10.076 --> 00:04:13.216 align:middle what we already know: it's called ControllerResolver 00:04:13.466 --> 00:04:15.256 align:middle and lives inside FrameworkBundle. 00:04:15.256 --> 00:04:18.726 align:middle So... let's open that up and see what it looks like! 00:04:19.196 --> 00:04:22.836 align:middle I'll hit Shift+Shift and look for ControllerResolver.php. 00:04:26.176 --> 00:04:33.316 align:middle Oh, there are two of them: the one from FrameworkBundle and another from HttpKernel. 00:04:34.016 --> 00:04:39.066 align:middle So... there's some inheritance going on: the ControllerResolver 00:04:39.066 --> 00:04:43.316 align:middle from FrameworkBundle extends a ContainerControllerResolver... 00:04:43.646 --> 00:04:47.606 align:middle which extends the ControllerResolver from HttpKernel. 00:04:48.516 --> 00:04:53.386 align:middle The class from FrameworkBundle doesn't contain anything important that we need to look at. 00:04:53.386 --> 00:04:57.676 align:middle So I'm actually going to open ContainerControllerResolver first. 00:04:58.376 --> 00:04:59.236 align:middle And... yep! 00:04:59.666 --> 00:05:04.336 align:middle Its base class is ControllerResolver, which lives in the same namespace. 00:05:05.336 --> 00:05:08.216 align:middle Hold Command or Ctrl and click that class to open it. 00:05:09.236 --> 00:05:11.186 align:middle Ok, time to see what's going on! 00:05:11.866 --> 00:05:14.766 align:middle HttpKernel called the getController() method. 00:05:15.306 --> 00:05:16.646 align:middle Let's go see what that looks like! 00:05:17.516 --> 00:05:20.576 align:middle The getController() method is passed the Request and... 00:05:21.066 --> 00:05:22.706 align:middle oh! Check it out! 00:05:23.146 --> 00:05:28.656 align:middle The first thing it does is fetch _controller from the request attributes! 00:05:29.336 --> 00:05:34.926 align:middle So why is _controller the "magic" key you can use in your YAML route? 00:05:35.386 --> 00:05:42.256 align:middle It's because of this line right here: the ControllerResolver looks for _controller. 00:05:43.186 --> 00:05:47.916 align:middle Ultimately, what this method needs to return is some sort of callable. 00:05:47.916 --> 00:05:53.956 align:middle For us, it will be a method inside an object, but it can also be a number 00:05:53.956 --> 00:05:56.986 align:middle of other things, like an anonymous function. 00:05:57.986 --> 00:06:00.596 align:middle Let's see what our $controller looks like at this point. 00:06:01.056 --> 00:06:05.096 align:middle dd($controller), then move back to your browser and refresh. 00:06:06.116 --> 00:06:10.856 align:middle Ah yes: for us, $controller is the normal string format we've been seeing: 00:06:11.276 --> 00:06:14.926 align:middle the full controller class, ::, then the method name. 00:06:17.036 --> 00:06:19.726 align:middle Remove the dd() and let's trace down on the code. 00:06:20.616 --> 00:06:24.686 align:middle This has a bunch of if statements, which are all basically trying to figure 00:06:24.686 --> 00:06:28.306 align:middle out if the controller is maybe already a callable. 00:06:28.946 --> 00:06:33.766 align:middle It checks if it's an array and if the 0 and 1 elements are set - 00:06:34.306 --> 00:06:36.176 align:middle because that's a callable format. 00:06:37.536 --> 00:06:39.396 align:middle We're also not an object... 00:06:39.396 --> 00:06:41.656 align:middle and our string is not a function name. 00:06:42.076 --> 00:06:45.606 align:middle Basically, our controller is not already a "callable". 00:06:46.546 --> 00:06:52.856 align:middle So ultimately, we fall down to $callable = $this->createController(). 00:06:53.526 --> 00:06:59.586 align:middle Somehow this function converts our string into something that can be invoked. 00:07:00.176 --> 00:07:02.246 align:middle How? Let's find out next.