First mark what you think will be used later:
Add route to the request ' s attributes in case a middleware or handler needs access to the Route$request = $request Withattribute (' Route ', $route);
Maybe later in the middleware to get the route to do something else.
The previous article has analyzed that the route is called in the app's __invoke (), here to see how to match the route. The approximate invocation process is as follows:
App->__invoke () \ $request = $this->dispatchrouterandprepareroute ($request, $router);
\ $routeInfo = $router->dispatch ($request);
\ $this->createdispatcher ()->dispatch ($request->getmethod (), $uri); (Tell if it is found and give the route's ID) \\FastRoute\simpleDispatcher (function (Routecollector $r) {}) (all the route is stored in Routecollector, and returngroupcountbased) \foreach ($this->getroutes () as $route) {
$r->addroute ($route->getmethods (), $route->getpattern (), $route->getidentifier ());
}
In App __invoke, you'll find a matching route. Route in the router, naturally to go to routers in search, called the $router->dispatch ($request). A dispatcher is created in the dispatch of router, $this->createdispatcher (). A namespace public function is used in Createdispatcher ()\fastroute\simpledispatcher (). It makes an array of each route's method (Get/post), pattern, identify into the routecollector, The Routecollector data is passed to groupcountbased through the groupcountbased construction method. The dispatch of $this->createdispatcher ()->dispatch ($request->getmethod (), $uri) is actually groupcountbased dispatch () Method. Groupcountbased->dispatch ($request->getmethod (), $uri) matches the corresponding route. The method of matching is actually very simple, is to determine whether the incoming method and URI in the array can be taken ($this->staticroutemap[$httpMethod [$uri] ). Returns the identify of the symbol or route that matches to or not. App->dispatchrouterandprepareroute () will keep the returned route matching results into the requst, so that the request will be directly able to get the corresponding route, think up the stick, but swollen to take it. App->__invoke () performs the execution of the route:
if ($routeInfo [0] = = = Dispatcher::found) { $route = $router->lookuproute ($routeInfo [1]); Return $route->run ($request, $response); } ElseIf ($routeInfo [0] = = = dispatcher::method_not_allowed) { if (! $this->container->has (' Notallowedhandler ') { throw new Methodnotallowedexception ($request, $response, $routeInfo [1]); } /** @var Callable $notAllowedHandler * /$notAllowedHandler = $this->container->get (' Notallowedhandler '); Return $notAllowedHandler ($request, $response, $routeInfo [1]); }
$route = $router->lookuproute ($routeInfo [1]); Find the route through the identify of the route.
Route->run executes the route.
The result of run is to execute its own __invoke, starting from all middleware, and the last element of the stack is itself.
/** * Dispatch Route callable against current Request and Response objects * * This method invokes the Rou Te object ' s callable. IF Middleware is * registered for the route, each callable middleware are invoked in * the order specified. * * @param serverrequestinterface $request The current request object * @param responseinterface $response T He current Response object * @return \psr\http\message\responseinterface * @throws \exception if the route Callab Le throws an exception * * Public function __invoke (serverrequestinterface $request, Responseinterface $response) {//debug_print_backtrace (); $this->callable = $this->resolvecallable ($this->callable); /** @var invocationstrategyinterface $handler */$handler = isset ($this->container)? $this->container->get (' Foundhandler '): New RequestResponse (); Invoke Route callable if ($this->outputbuffering = = = False) { $newResponse = $handler ($this->callable, $request, $response, $this->arguments); } else {try {ob_start (); $newResponse = $handler ($this->callable, $request, $response, $this->arguments); $output = Ob_get_clean (); } catch (Exception $e) {Ob_end_clean (); Throw $e; }} if ($newResponse instanceof responseinterface) {//If route callback returns a Responseinter Face, then use it $response = $newResponse; } elseif (Is_string ($newResponse)) {//If route callback returns a string, then append it to the response if ($response->getbody ()->iswritable ()) {$response->getbody ()->write ($newResponse); }} if (!empty ($output) && $response->getbody ()->iswritable ()) {if ($this ->outputbuffering = = = ' Prepend ') { Prepend Output Buffer Content $body = new Http\body (fopen (' php://temp ', ' r+ ')); $body->write ($output. $response->getbody ()); $response = $response->withbody ($body); } elseif ($this->outputbuffering = = = ' Append ') {//Append output buffer content $respons E->getbody ()->write ($output); }} return $response; }
$this->callable = $this->resolvecallable ($this->callable); The Class::method callback form a normal callback. $handler is to find the strategy that will be executed at handler Call_user_func (), which is the closure function of the route, is executed, that is, the route is executed at this time. This will get reponse returned or the resulting string results will be written to the Web page.
Learn how slim Framework for PHP v3 (vi)--route is matched?