{"id":838,"date":"2014-10-08T14:20:18","date_gmt":"2014-10-08T06:20:18","guid":{"rendered":"http:\/\/blog.turn.tw\/?page_id=838"},"modified":"2014-10-11T20:41:36","modified_gmt":"2014-10-11T12:41:36","slug":"%e5%88%86%e9%85%8d%e5%b7%a5%e4%bd%9c%ef%bc%9aroutingrouter-php","status":"publish","type":"page","link":"https:\/\/blog.turn.tw\/?page_id=838","title":{"rendered":"\u5206\u914d\u5de5\u4f5c\uff1aRouting\/Router.php"},"content":{"rendered":"<p>\u8207routing\u76f8\u95dc\u7684\u4e00\u5207\u90fd\u900f\u904e\u6b64Router\u985e\u5225\u5b8c\u6210\u3002<br \/>\n\u7531\u65bcLaravel\u652f\u63f4\u7684routing\u65b9\u5f0f\u975e\u5e38\u591a\u5143\uff0c\u9664\u4e86\u5e38\u898b\u7684\u5c0d\u61c9\u5230closure\u3001\u5c0d\u61c9\u5230\u7279\u5b9acontroller\u7684\u7279\u5b9a\u51fd\u5f0f\uff0c\u9084\u652f\u63f4\u4e86route filters\u3001route groups\u7b49\u529f\u80fd\u3002\u6240\u4ee5\uff0c\u8981\u770b\u61c2\u5168\u90e8source code\uff0c\u9700\u8981\u5148\u77ad\u89e3Laravel\u63d0\u4f9b\u4e86\u54ea\u4e9b\u8c50\u5bcc\u7684routing\u65b9\u6cd5\uff1a<a href=\"http:\/\/laravel.com\/docs\/4.2\/routing\" title=\"Routing\">Routing<\/a><\/p>\n<pre>\r\n<?php namespace Illuminate\\Routing;\r\n\r\nuse Closure;\r\nuse Illuminate\\Http\\Request;\r\nuse Illuminate\\Http\\Response;\r\nuse Illuminate\\Events\\Dispatcher;\r\nuse Illuminate\\Container\\Container;\r\nuse Symfony\\Component\\HttpKernel\\HttpKernelInterface;\r\nuse Symfony\\Component\\HttpFoundation\\Request as SymfonyRequest;\r\nuse Symfony\\Component\\HttpFoundation\\Response as SymfonyResponse;\r\nuse Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException;\r\n\r\nclass Router implements HttpKernelInterface, RouteFiltererInterface {\r\n\r\n\t\/**\r\n\t * The event dispatcher instance.\r\n\t *\r\n\t * @var \\Illuminate\\Events\\Dispatcher\r\n\t *\/\r\n\tprotected $events;\r\n\r\n\t\/**\r\n\t * The IoC container instance.\r\n\t *\r\n\t * @var \\Illuminate\\Container\\Container\r\n\t *\/\r\n\tprotected $container;\r\n\r\n\t\/**\r\n\t * The route collection instance.\r\n\t *\r\n\t * @var \\Illuminate\\Routing\\RouteCollection\r\n\t *\/\r\n\tprotected $routes;\r\n\r\n\t\/**\r\n\t * The currently dispatched route instance.\r\n\t *\r\n\t * @var \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected $current;\r\n\r\n\t\/**\r\n\t * The request currently being dispatched.\r\n\t *\r\n\t * @var \\Illuminate\\Http\\Request\r\n\t *\/\r\n\tprotected $currentRequest;\r\n\r\n\t\/**\r\n\t * The controller dispatcher instance.\r\n\t *\r\n\t * @var \\Illuminate\\Routing\\ControllerDispatcher\r\n\t *\/\r\n\tprotected $controllerDispatcher;\r\n\r\n\t\/**\r\n\t * The controller inspector instance.\r\n\t *\r\n\t * @var \\Illuminate\\Routing\\ControllerInspector\r\n\t *\/\r\n\tprotected $inspector;\r\n\r\n\t\/**\r\n\t * Indicates if the router is running filters.\r\n\t *\r\n\t * @var bool\r\n\t *\/\r\n\tprotected $filtering = true;\r\n\r\n\t\/**\r\n\t * The registered pattern based filters.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $patternFilters = array();\r\n\r\n\t\/**\r\n\t * The registered regular expression based filters.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $regexFilters = array();\r\n\r\n\t\/**\r\n\t * The registered route value binders.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $binders = array();\r\n\r\n\t\/**\r\n\t * The globally available parameter patterns.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $patterns = array();\r\n\r\n\t\/**\r\n\t * The route group attribute stack.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $groupStack = array();\r\n\r\n\t\/**\r\n\t * All of the verbs supported by the router.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tpublic static $verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS');\r\n\r\n\t\/**\r\n\t * The default actions for a resourceful controller.\r\n\t *\r\n\t * @var array\r\n\t *\/\r\n\tprotected $resourceDefaults = array('index', 'create', 'store', 'show', 'edit', 'update', 'destroy');\r\n\r\n\t\/**\r\n\t * Create a new Router instance.\r\n\t *\r\n\t * @param  \\Illuminate\\Events\\Dispatcher  $events\r\n\t * @param  \\Illuminate\\Container\\Container  $container\r\n\t * @return void\r\n\t *\/\r\n\tpublic function __construct(Dispatcher $events, Container $container = null)\r\n\t{\r\n\t\t$this->events = $events;\r\n\t\t$this->routes = new RouteCollection;\r\n\t\t$this->container = $container ?: new Container;\r\n\r\n\t\t$this->bind('_missing', function($v) { return explode('\/', $v); });\r\n\t}\r\n<\/pre>\n<p>\u5efa\u69cb\u5f0f\u6703\u5c07$events\u5b58\u4e0b\u3001$app\u5b58\u70ba$container(\uff1f\uff1f\uff1f)<br \/>\n\u8def\u5f91\u7d44\u7684\u5c0d\u61c9\u662f\u7531Symfony\u7684RouteCollection\u985e\u5225\u8ca0\u8cac\u3002<br \/>\nRouter\u5be6\u4f5c\u4e0a\u7684\u6838\u5fc3\u529f\u80fd\u662f\u7531Symfony\u7684RouteCollection\u8207Route\u985e\u5225\u5b8c\u6210\u3002<\/p>\n<pre>\r\n\r\n\r\n\r\n\t\/**\r\n\t * Register a new GET route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function get($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute(['GET', 'HEAD'], $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new POST route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function post($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute('POST', $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new PUT route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function put($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute('PUT', $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new PATCH route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function patch($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute('PATCH', $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new DELETE route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function delete($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute('DELETE', $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new OPTIONS route with the router.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function options($uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute('OPTIONS', $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new route responding to all verbs.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function any($uri, $action)\r\n\t{\r\n\t\t$verbs = array('GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE');\r\n\r\n\t\treturn $this->addRoute($verbs, $uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new route with the given verbs.\r\n\t *\r\n\t * @param  array|string  $methods\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function match($methods, $uri, $action)\r\n\t{\r\n\t\treturn $this->addRoute(array_map('strtoupper', (array) $methods), $uri, $action);\r\n\t}\r\n<\/pre>\n<p>\u4ee5\u4e0aget, post, put, patch, delete, options, any, match\u51fd\u5f0f\uff0c\u90fd\u53ea\u662f\u547c\u53ebaddRoute\u65b0\u589e\u4e00\u500broute\u3002<br \/>\n\u4f7f\u7528Laravel\u6642\uff0c\u64b0\u5beb\u7684route\u898f\u5247\u5c31\u662f\u5728\u547c\u53eb\u9019\u4e9b\u51fd\u5f0f\uff1a<a href=\"http:\/\/laravel.com\/docs\/4.2\/routing\" title=\"Routing\">Routing<\/a><br \/>\n\u82e5\u662f\u597d\u5947\u80cc\u5f8c\u7684\u547c\u53eb\u539f\u7406\uff0c\u8acb\u53c3\u898b\uff1a<a href=\"https:\/\/blog.turn.tw\/?page_id=875\" title=\"\u8b93\u4f60\u5c11\u6253\u5f88\u591a\u5b57\uff1aFacades\u3002\">\u8b93\u4f60\u5c11\u6253\u5f88\u591a\u5b57\uff1aFacades\u3002<\/a><\/p>\n<pre>\r\n\r\n\t\/**\r\n\t * Register an array of controllers with wildcard routing.\r\n\t *\r\n\t * @param  array  $controllers\r\n\t * @return void\r\n\t *\/\r\n\tpublic function controllers(array $controllers)\r\n\t{\r\n\t\tforeach ($controllers as $uri => $name)\r\n\t\t{\r\n\t\t\t$this->controller($uri, $name);\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Route a controller to a URI with wildcard routing.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @param  string  $controller\r\n\t * @param  array   $names\r\n\t * @return void\r\n\t *\/\r\n\tpublic function controller($uri, $controller, $names = array())\r\n\t{\r\n\t\t$prepended = $controller;\r\n\r\n\t\t\/\/ First, we will check to see if a controller prefix has been registered in\r\n\t\t\/\/ the route group. If it has, we will need to prefix it before trying to\r\n\t\t\/\/ reflect into the class instance and pull out the method for routing.\r\n\t\tif ( ! empty($this->groupStack))\r\n\t\t{\r\n\t\t\t$prepended = $this->prependGroupUses($controller);\r\n\t\t}\r\n\r\n\t\t$routable = $this->getInspector()->getRoutable($prepended, $uri);\r\n\r\n\t\t\/\/ When a controller is routed using this method, we use Reflection to parse\r\n\t\t\/\/ out all of the routable methods for the controller, then register each\r\n\t\t\/\/ route explicitly for the developers, so reverse routing is possible.\r\n\t\tforeach ($routable as $method => $routes)\r\n\t\t{\r\n\t\t\tforeach ($routes as $route)\r\n\t\t\t{\r\n\t\t\t\t$this->registerInspected($route, $controller, $method, $names);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t$this->addFallthroughRoute($controller, $uri);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register an inspected controller route.\r\n\t *\r\n\t * @param  array   $route\r\n\t * @param  string  $controller\r\n\t * @param  string  $method\r\n\t * @param  array   $names\r\n\t * @return void\r\n\t *\/\r\n\tprotected function registerInspected($route, $controller, $method, &$names)\r\n\t{\r\n\t\t$action = array('uses' => $controller.'@'.$method);\r\n\r\n\t\t\/\/ If a given controller method has been named, we will assign the name to the\r\n\t\t\/\/ controller action array, which provides for a short-cut to method naming\r\n\t\t\/\/ so you don't have to define an individual route for these controllers.\r\n\t\t$action['as'] = array_get($names, $method);\r\n\r\n\t\t$this->{$route['verb']}($route['uri'], $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add a fallthrough route for a controller.\r\n\t *\r\n\t * @param  string  $controller\r\n\t * @param  string  $uri\r\n\t * @return void\r\n\t *\/\r\n\tprotected function addFallthroughRoute($controller, $uri)\r\n\t{\r\n\t\t$missing = $this->any($uri.'\/{_missing}', $controller.'@missingMethod');\r\n\r\n\t\t$missing->where('_missing', '(.*)');\r\n\t}\r\n\r\n\t\/**\r\n\t * Route a resource to a controller.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return void\r\n\t *\/\r\n\tpublic function resource($name, $controller, array $options = array())\r\n\t{\r\n\t\t\/\/ If the resource name contains a slash, we will assume the developer wishes to\r\n\t\t\/\/ register these resource routes with a prefix so we will set that up out of\r\n\t\t\/\/ the box so they don't have to mess with it. Otherwise, we will continue.\r\n\t\tif (str_contains($name, '\/'))\r\n\t\t{\r\n\t\t\t$this->prefixedResource($name, $controller, $options);\r\n\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\t\/\/ We need to extract the base resource from the resource name. Nested resources\r\n\t\t\/\/ are supported in the framework, but we need to know what name to use for a\r\n\t\t\/\/ place-holder on the route wildcards, which should be the base resources.\r\n\t\t$base = $this->getResourceWildcard(last(explode('.', $name)));\r\n\r\n\t\t$defaults = $this->resourceDefaults;\r\n\r\n\t\tforeach ($this->getResourceMethods($defaults, $options) as $m)\r\n\t\t{\r\n\t\t\t$this->{'addResource'.ucfirst($m)}($name, $base, $controller, $options);\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Build a set of prefixed resource routes.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return void\r\n\t *\/\r\n\tprotected function prefixedResource($name, $controller, array $options)\r\n\t{\r\n\t\tlist($name, $prefix) = $this->getResourcePrefix($name);\r\n\r\n\t\t\/\/ We need to extract the base resource from the resource name. Nested resources\r\n\t\t\/\/ are supported in the framework, but we need to know what name to use for a\r\n\t\t\/\/ place-holder on the route wildcards, which should be the base resources.\r\n\t\t$callback = function($me) use ($name, $controller, $options)\r\n\t\t{\r\n\t\t\t$me->resource($name, $controller, $options);\r\n\t\t};\r\n\r\n\t\treturn $this->group(compact('prefix'), $callback);\r\n\t}\r\n\r\n\t\/**\r\n\t * Extract the resource and prefix from a resource name.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @return array\r\n\t *\/\r\n\tprotected function getResourcePrefix($name)\r\n\t{\r\n\t\t$segments = explode('\/', $name);\r\n\r\n\t\t\/\/ To get the prefix, we will take all of the name segments and implode them on\r\n\t\t\/\/ a slash. This will generate a proper URI prefix for us. Then we take this\r\n\t\t\/\/ last segment, which will be considered the final resources name we use.\r\n\t\t$prefix = implode('\/', array_slice($segments, 0, -1));\r\n\r\n\t\treturn array(end($segments), $prefix);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the applicable resource methods.\r\n\t *\r\n\t * @param  array  $defaults\r\n\t * @param  array  $options\r\n\t * @return array\r\n\t *\/\r\n\tprotected function getResourceMethods($defaults, $options)\r\n\t{\r\n\t\tif (isset($options['only']))\r\n\t\t{\r\n\t\t\treturn array_intersect($defaults, (array) $options['only']);\r\n\t\t}\r\n\t\telseif (isset($options['except']))\r\n\t\t{\r\n\t\t\treturn array_diff($defaults, (array) $options['except']);\r\n\t\t}\r\n\r\n\t\treturn $defaults;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the base resource URI for a given resource.\r\n\t *\r\n\t * @param  string  $resource\r\n\t * @return string\r\n\t *\/\r\n\tpublic function getResourceUri($resource)\r\n\t{\r\n\t\tif ( ! str_contains($resource, '.')) return $resource;\r\n\r\n\t\t\/\/ Once we have built the base URI, we'll remove the wildcard holder for this\r\n\t\t\/\/ base resource name so that the individual route adders can suffix these\r\n\t\t\/\/ paths however they need to, as some do not have any wildcards at all.\r\n\t\t$segments = explode('.', $resource);\r\n\r\n\t\t$uri = $this->getNestedResourceUri($segments);\r\n\r\n\t\treturn str_replace('\/{'.$this->getResourceWildcard(last($segments)).'}', '', $uri);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the URI for a nested resource segment array.\r\n\t *\r\n\t * @param  array   $segments\r\n\t * @return string\r\n\t *\/\r\n\tprotected function getNestedResourceUri(array $segments)\r\n\t{\r\n\t\t\/\/ We will spin through the segments and create a place-holder for each of the\r\n\t\t\/\/ resource segments, as well as the resource itself. Then we should get an\r\n\t\t\/\/ entire string for the resource URI that contains all nested resources.\r\n\t\treturn implode('\/', array_map(function($s)\r\n\t\t{\r\n\t\t\treturn $s.'\/{'.$this->getResourceWildcard($s).'}';\r\n\r\n\t\t}, $segments));\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the action array for a resource route.\r\n\t *\r\n\t * @param  string  $resource\r\n\t * @param  string  $controller\r\n\t * @param  string  $method\r\n\t * @param  array   $options\r\n\t * @return array\r\n\t *\/\r\n\tprotected function getResourceAction($resource, $controller, $method, $options)\r\n\t{\r\n\t\t$name = $this->getResourceName($resource, $method, $options);\r\n\r\n\t\treturn array('as' => $name, 'uses' => $controller.'@'.$method);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the name for a given resource.\r\n\t *\r\n\t * @param  string  $resource\r\n\t * @param  string  $method\r\n\t * @param  array   $options\r\n\t * @return string\r\n\t *\/\r\n\tprotected function getResourceName($resource, $method, $options)\r\n\t{\r\n\t\tif (isset($options['names'][$method])) return $options['names'][$method];\r\n\r\n\t\t\/\/ If a global prefix has been assigned to all names for this resource, we will\r\n\t\t\/\/ grab that so we can prepend it onto the name when we create this name for\r\n\t\t\/\/ the resource action. Otherwise we'll just use an empty string for here.\r\n\t\t$prefix = isset($options['as']) ? $options['as'].'.' : '';\r\n\r\n\t\tif (empty($this->groupStack))\r\n\t\t{\r\n\t\t\treturn $prefix.$resource.'.'.$method;\r\n\t\t}\r\n\r\n\t\treturn $this->getGroupResourceName($prefix, $resource, $method);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the resource name for a grouped resource.\r\n\t *\r\n\t * @param  string  $prefix\r\n\t * @param  string  $resource\r\n\t * @param  string  $method\r\n\t * @return string\r\n\t *\/\r\n\tprotected function getGroupResourceName($prefix, $resource, $method)\r\n\t{\r\n\t\t$group = str_replace('\/', '.', $this->getLastGroupPrefix());\r\n\r\n\t\treturn trim(\"{$prefix}{$group}.{$resource}.{$method}\", '.');\r\n\t}\r\n\r\n\t\/**\r\n\t * Format a resource wildcard for usage.\r\n\t *\r\n\t * @param  string  $value\r\n\t * @return string\r\n\t *\/\r\n\tpublic function getResourceWildcard($value)\r\n\t{\r\n\t\treturn str_replace('-', '_', $value);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the index method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceIndex($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name);\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'index', $options);\r\n\r\n\t\treturn $this->get($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the create method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceCreate($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/create';\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'create', $options);\r\n\r\n\t\treturn $this->get($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the store method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceStore($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name);\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'store', $options);\r\n\r\n\t\treturn $this->post($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the show method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceShow($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/{'.$base.'}';\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'show', $options);\r\n\r\n\t\treturn $this->get($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the edit method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceEdit($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/{'.$base.'}\/edit';\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'edit', $options);\r\n\r\n\t\treturn $this->get($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the update method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return void\r\n\t *\/\r\n\tprotected function addResourceUpdate($name, $base, $controller, $options)\r\n\t{\r\n\t\t$this->addPutResourceUpdate($name, $base, $controller, $options);\r\n\r\n\t\treturn $this->addPatchResourceUpdate($name, $base, $controller);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the update method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addPutResourceUpdate($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/{'.$base.'}';\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'update', $options);\r\n\r\n\t\treturn $this->put($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the update method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @return void\r\n\t *\/\r\n\tprotected function addPatchResourceUpdate($name, $base, $controller)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/{'.$base.'}';\r\n\r\n\t\t$this->patch($uri, $controller.'@update');\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the destroy method for a resourceful route.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string  $base\r\n\t * @param  string  $controller\r\n\t * @param  array   $options\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addResourceDestroy($name, $base, $controller, $options)\r\n\t{\r\n\t\t$uri = $this->getResourceUri($name).'\/{'.$base.'}';\r\n\r\n\t\t$action = $this->getResourceAction($name, $controller, 'destroy', $options);\r\n\r\n\t\treturn $this->delete($uri, $action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Create a route group with shared attributes.\r\n\t *\r\n\t * @param  array     $attributes\r\n\t * @param  \\Closure  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function group(array $attributes, Closure $callback)\r\n\t{\r\n\t\t$this->updateGroupStack($attributes);\r\n\r\n\t\t\/\/ Once we have updated the group stack, we will execute the user Closure and\r\n\t\t\/\/ merge in the groups attributes when the route is created. After we have\r\n\t\t\/\/ run the callback, we will pop the attributes off of this group stack.\r\n\t\tcall_user_func($callback, $this);\r\n\r\n\t\tarray_pop($this->groupStack);\r\n\t}\r\n\r\n\t\/**\r\n\t * Update the group stack with the given attributes.\r\n\t *\r\n\t * @param  array  $attributes\r\n\t * @return void\r\n\t *\/\r\n\tprotected function updateGroupStack(array $attributes)\r\n\t{\r\n\t\tif ( ! empty($this->groupStack))\r\n\t\t{\r\n\t\t\t$attributes = $this->mergeGroup($attributes, last($this->groupStack));\r\n\t\t}\r\n\r\n\t\t$this->groupStack[] = $attributes;\r\n\t}\r\n\r\n\t\/**\r\n\t * Merge the given array with the last group stack.\r\n\t *\r\n\t * @param  array  $new\r\n\t * @return array\r\n\t *\/\r\n\tpublic function mergeWithLastGroup($new)\r\n\t{\r\n\t\treturn $this->mergeGroup($new, last($this->groupStack));\r\n\t}\r\n\r\n\t\/**\r\n\t * Merge the given group attributes.\r\n\t *\r\n\t * @param  array  $new\r\n\t * @param  array  $old\r\n\t * @return array\r\n\t *\/\r\n\tpublic static function mergeGroup($new, $old)\r\n\t{\r\n\t\t$new['namespace'] = static::formatUsesPrefix($new, $old);\r\n\r\n\t\t$new['prefix'] = static::formatGroupPrefix($new, $old);\r\n\r\n\t\tif (isset($new['domain'])) unset($old['domain']);\r\n\r\n\t\t$new['where'] = array_merge(array_get($old, 'where', []), array_get($new, 'where', []));\r\n\r\n\t\treturn array_merge_recursive(array_except($old, array('namespace', 'prefix', 'where')), $new);\r\n\t}\r\n\r\n\t\/**\r\n\t * Format the uses prefix for the new group attributes.\r\n\t *\r\n\t * @param  array  $new\r\n\t * @param  array  $old\r\n\t * @return string\r\n\t *\/\r\n\tprotected static function formatUsesPrefix($new, $old)\r\n\t{\r\n\t\tif (isset($new['namespace']) && isset($old['namespace']))\r\n\t\t{\r\n\t\t\treturn trim(array_get($old, 'namespace'), '\\\\').'\\\\'.trim($new['namespace'], '\\\\');\r\n\t\t}\r\n\t\telseif (isset($new['namespace']))\r\n\t\t{\r\n\t\t\treturn trim($new['namespace'], '\\\\');\r\n\t\t}\r\n\r\n\t\treturn array_get($old, 'namespace');\r\n\t}\r\n\r\n\t\/**\r\n\t * Format the prefix for the new group attributes.\r\n\t *\r\n\t * @param  array  $new\r\n\t * @param  array  $old\r\n\t * @return string\r\n\t *\/\r\n\tprotected static function formatGroupPrefix($new, $old)\r\n\t{\r\n\t\tif (isset($new['prefix']))\r\n\t\t{\r\n\t\t\treturn trim(array_get($old, 'prefix'), '\/').'\/'.trim($new['prefix'], '\/');\r\n\t\t}\r\n\r\n\t\treturn array_get($old, 'prefix');\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the prefix from the last group on the stack.\r\n\t *\r\n\t * @return string\r\n\t *\/\r\n\tprotected function getLastGroupPrefix()\r\n\t{\r\n\t\tif ( ! empty($this->groupStack))\r\n\t\t{\r\n\t\t\t$last = end($this->groupStack);\r\n\t\t\treturn isset($last['prefix']) ? $last['prefix'] : '';\r\n\t\t}\r\n\r\n\t\treturn '';\r\n\t}\r\n\r\n\t\/**\r\n\t * Add a route to the underlying route collection.\r\n\t *\r\n\t * @param  array|string  $methods\r\n\t * @param  string  $uri\r\n\t * @param  \\Closure|array|string  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addRoute($methods, $uri, $action)\r\n\t{\r\n\t\treturn $this->routes->add($this->createRoute($methods, $uri, $action));\r\n\t}\r\n<\/pre>\n<p>addRoute\u5c31\u662f\u5728$this->routes\u9019\u500bRouteCollection\u5be6\u9ad4\u5167add\u4e00\u500bRoute\u5be6\u9ad4\u800c\u5df2\u3002<\/p>\n<pre>\r\n\r\n\t\/**\r\n\t * Create a new route instance.\r\n\t *\r\n\t * @param  array|string  $methods\r\n\t * @param  string  $uri\r\n\t * @param  mixed   $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function createRoute($methods, $uri, $action)\r\n\t{\r\n\t\t\/\/ If the route is routing to a controller we will parse the route action into\r\n\t\t\/\/ an acceptable array format before registering it and creating this route\r\n\t\t\/\/ instance itself. We need to build the Closure that will call this out.\r\n\t\tif ($this->routingToController($action))\r\n\t\t{\r\n\t\t\t$action = $this->getControllerAction($action);\r\n\t\t}\r\n\r\n\t\t$route = $this->newRoute(\r\n\t\t\t$methods, $uri = $this->prefix($uri), $action\r\n\t\t);\r\n\r\n\t\t\/\/ If we have groups that need to be merged, we will merge them now after this\r\n\t\t\/\/ route has already been created and is ready to go. After we're done with\r\n\t\t\/\/ the merge we will be ready to return the route back out to the caller.\r\n\t\tif ( ! empty($this->groupStack))\r\n\t\t{\r\n\t\t\t$this->mergeController($route);\r\n\t\t}\r\n\r\n\t\t$this->addWhereClausesToRoute($route);\r\n\r\n\t\treturn $route;\r\n\t}\r\n<\/pre>\n<p>\u5148\u7528routingToController\u5224\u65b7$action\u5230\u5e95\u662f\u4e00\u500b\u53ef\u547c\u53eb\u7684callback\uff0c\u9084\u662f\u4ee3\u8868\u4e86controller\u7684\u5b57\u4e32\u3002<br \/>\n\u5982\u679c\u662f\u4ee3\u8868\u4e86controller\u7684\u5b57\u4e32\uff0c\uff1f\uff1f\uff1f<br \/>\ncreateRoute\u6703\u53bb\u547c\u53ebnewRoute\u4f86\u521d\u59cb\u5316\u4e00\u500broute\u3002<\/p>\n<pre>\r\n\t\/**\r\n\t * Create a new Route object.\r\n\t *\r\n\t * @param  array|string $methods\r\n\t * @param  string  $uri\r\n\t * @param  mixed  $action\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function newRoute($methods, $uri, $action)\r\n\t{\r\n\t\treturn new Route($methods, $uri, $action);\r\n\t}\r\n<\/pre>\n<p>newRoute\u53ea\u662f\u547c\u53ebRoute\u5efa\u69cb\u5f0f\u7136\u5f8c\u56de\u50b3\u800c\u5df2\u3002<br \/>\n<red><br \/>\n\u9664\u4e86\u547c\u53eb\u5efa\u69cb\u5f0f\uff0c\u4ec0\u9ebc\u90fd\u6c92\u505a\u3002<br \/>\n\u4e00\u5b9a\u8981\u591a\u5beb\u9019\u500bnewRoute\u7d66createRoute\u547c\u53eb\u55ce\uff1fcreateRoute\u4e0d\u80fd\u76f4\u63a5\u547c\u53eb\u5efa\u69cb\u5f0f\u55ce\uff1f<br \/>\n\u6211\u89ba\u5f97\u591a\u6b64\u4e00\u8209\u3002<br \/>\n<\/red><\/p>\n<pre>\r\n\t\/**\r\n\t * Prefix the given URI with the last prefix.\r\n\t *\r\n\t * @param  string  $uri\r\n\t * @return string\r\n\t *\/\r\n\tprotected function prefix($uri)\r\n\t{\r\n\t\treturn trim(trim($this->getLastGroupPrefix(), '\/').'\/'.trim($uri, '\/'), '\/') ?: '\/';\r\n\t}\r\n\r\n\t\/**\r\n\t * Add the necessary where clauses to the route based on its initial registration.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function addWhereClausesToRoute($route)\r\n\t{\r\n\t\t$route->where(\r\n\t\t\tarray_merge($this->patterns, array_get($route->getAction(), 'where', []))\r\n\t\t);\r\n\r\n\t\treturn $route;\r\n\t}\r\n\r\n\t\/**\r\n\t * Merge the group stack with the controller action.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @return void\r\n\t *\/\r\n\tprotected function mergeController($route)\r\n\t{\r\n\t\t$action = $this->mergeWithLastGroup($route->getAction());\r\n\r\n\t\t$route->setAction($action);\r\n\t}\r\n\r\n\t\/**\r\n\t * Determine if the action is routing to a controller.\r\n\t *\r\n\t * @param  array  $action\r\n\t * @return bool\r\n\t *\/\r\n\tprotected function routingToController($action)\r\n\t{\r\n\t\tif ($action instanceof Closure) return false;\r\n\r\n\t\treturn is_string($action) || is_string(array_get($action, 'uses'));\r\n\t}\r\n<\/pre>\n<p>\u5224\u65b7\u662f\u5426\u70ba\u4ee3\u8868controller\u7684route\u5b57\u4e32\u3002<br \/>\n<red><br \/>\n\u56de\u50b3Boolean\u7684\u51fd\u5f0f\u901a\u5e38\u547d\u540d\u4ee5is\u958b\u982d\u8f03\u597d\u3002<br \/>\n\u8b6c\u5982isRoutedToController\u3002<br \/>\n<\/red><\/p>\n<pre>\r\n\t\/**\r\n\t * Add a controller based route action to the action array.\r\n\t *\r\n\t * @param  array|string  $action\r\n\t * @return array\r\n\t *\/\r\n\tprotected function getControllerAction($action)\r\n\t{\r\n\t\tif (is_string($action)) $action = array('uses' => $action);\r\n\r\n\t\t\/\/ Here we'll get an instance of this controller dispatcher and hand it off to\r\n\t\t\/\/ the Closure so it will be used to resolve the class instances out of our\r\n\t\t\/\/ IoC container instance and call the appropriate methods on the class.\r\n\t\tif ( ! empty($this->groupStack))\r\n\t\t{\r\n\t\t\t$action['uses'] = $this->prependGroupUses($action['uses']);\r\n\t\t}\r\n\r\n\t\t\/\/ Here we'll get an instance of this controller dispatcher and hand it off to\r\n\t\t\/\/ the Closure so it will be used to resolve the class instances out of our\r\n\t\t\/\/ IoC container instance and call the appropriate methods on the class.\r\n\t\t$action['controller'] = $action['uses'];\r\n\r\n\t\t$closure = $this->getClassClosure($action['uses']);\r\n\r\n\t\treturn array_set($action, 'uses', $closure);\r\n\t}\r\n<\/pre>\n<p>$action\u8981\u561b\u662f\u4ee3\u8868controller\u7684\u5b57\u4e32\uff0c\u8981\u561b\u662f\u4e00\u500b\u6709&#8217;uses&#8217;\u7d22\u5f15\u7684\u9663\u5217\u3002<br \/>\n\u82e5\u662f\u524d\u8005\u7684\u5f62\u5f0f\uff0c\u7d71\u4e00\u628a\u5b83\u8f49\u6210\u5f8c\u8005\u7684\u5f62\u5f0f\u3002<\/p>\n<p>\u7136\u5f8c&#8230;\uff1f\uff1f\uff1f<\/p>\n<pre>\r\n\t\/**\r\n\t * Get the Closure for a controller based action.\r\n\t *\r\n\t * @param  string  $controller\r\n\t * @return \\Closure\r\n\t *\/\r\n\tprotected function getClassClosure($controller)\r\n\t{\r\n\t\t\/\/ Here we'll get an instance of this controller dispatcher and hand it off to\r\n\t\t\/\/ the Closure so it will be used to resolve the class instances out of our\r\n\t\t\/\/ IoC container instance and call the appropriate methods on the class.\r\n\t\t$d = $this->getControllerDispatcher();\r\n\r\n\t\treturn function() use ($d, $controller)\r\n\t\t{\r\n\t\t\t$route = $this->current();\r\n\r\n\t\t\t$request = $this->getCurrentRequest();\r\n\r\n\t\t\t\/\/ Now we can split the controller and method out of the action string so that we\r\n\t\t\t\/\/ can call them appropriately on the class. This controller and method are in\r\n\t\t\t\/\/ in the Class@method format and we need to explode them out then use them.\r\n\t\t\tlist($class, $method) = explode('@', $controller);\r\n\r\n\t\t\treturn $d->dispatch($route, $request, $class, $method);\r\n\t\t};\r\n\t}\r\n\r\n\t\/**\r\n\t * Prepend the last group uses onto the use clause.\r\n\t *\r\n\t * @param  string  $uses\r\n\t * @return string\r\n\t *\/\r\n\tprotected function prependGroupUses($uses)\r\n\t{\r\n\t\t$group = last($this->groupStack);\r\n\r\n\t\treturn isset($group['namespace']) ? $group['namespace'].'\\\\'.$uses : $uses;\r\n\t}\r\n\r\n\t\/**\r\n\t * Dispatch the request to the application.\r\n\t *\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return \\Illuminate\\Http\\Response\r\n\t *\/\r\n\tpublic function dispatch(Request $request)\r\n\t{\r\n\t\t$this->currentRequest = $request;\r\n\r\n\t\t\/\/ If no response was returned from the before filter, we will call the proper\r\n\t\t\/\/ route instance to get the response. If no route is found a response will\r\n\t\t\/\/ still get returned based on why no routes were found for this request.\r\n\t\t$response = $this->callFilter('before', $request);\r\n\r\n\t\tif (is_null($response))\r\n\t\t{\r\n\t\t\t$response = $this->dispatchToRoute($request);\r\n\t\t}\r\n\r\n\t\t$response = $this->prepareResponse($request, $response);\r\n\r\n\t\t\/\/ Once this route has run and the response has been prepared, we will run the\r\n\t\t\/\/ after filter to do any last work on the response or for this application\r\n\t\t\/\/ before we will return the response back to the consuming code for use.\r\n\t\t$this->callFilter('after', $request, $response);\r\n\r\n\t\treturn $response;\r\n\t}\r\n<\/pre>\n<p>\u5be6\u969b\u4e0a\u8ca0\u8cac\u5206\u914d\u4efb\u52d9\u7684\u51fd\u5f0f\u3002<br \/>\n\u5148\u7d00\u9304\u672c\u6b21$request\u3002\u63a5\u8457\u6aa2\u67e5\u6709\u6c92\u6709\u91dd\u5c0d\u6b64request\u767b\u8a18\u9810\u5148\u8655\u7406\u7684\u52d5\u4f5c(\u6c92\u6709\u7684\u8a71\uff0ccallFilter\u6703\u56de\u50b3null)\u3002<br \/>\n\u82e5before\u7684\u52d5\u4f5c\u7d50\u675f\u9084\u6c92\u5f97\u5230response\uff0c\u5247dispatchToRoute\u6703\u53bb\u627e\u5c0d\u61c9\u7684Controller\u4e4b\u985e\u7684\u53bb\u8655\u7406\u3002<br \/>\nprepareResponse\u6703\u5c07$response\u8abf\u6574\u3001\u4f7f\u5176\u7b26\u5408RFC 2616\u7684\u898f\u7bc4\u3002<br \/>\n\u6700\u5f8c\u6aa2\u67e5\u6709\u6c92\u6709\u91dd\u5c0d\u6b64request\u767b\u8a18\u5f8c\u7e8c\u8655\u7406\u7684\u52d5\u4f5c\u3002<\/p>\n<pre>\r\n\r\n\t\/**\r\n\t * Dispatch the request to a route and return the response.\r\n\t *\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return mixed\r\n\t *\/\r\n\tpublic function dispatchToRoute(Request $request)\r\n\t{\r\n\t\t$route = $this->findRoute($request);\r\n\r\n\t\t$this->events->fire('router.matched', array($route, $request));\r\n\r\n\t\t\/\/ Once we have successfully matched the incoming request to a given route we\r\n\t\t\/\/ can call the before filters on that route. This works similar to global\r\n\t\t\/\/ filters in that if a response is returned we will not call the route.\r\n\t\t$response = $this->callRouteBefore($route, $request);\r\n\r\n\t\tif (is_null($response))\r\n\t\t{\r\n\t\t\t$response = $route->run($request);\r\n\t\t}\r\n\r\n\t\t$response = $this->prepareResponse($request, $response);\r\n\r\n\t\t\/\/ After we have a prepared response from the route or filter we will call to\r\n\t\t\/\/ the \"after\" filters to do any last minute processing on this request or\r\n\t\t\/\/ response object before the response is returned back to the consumer.\r\n\t\t$this->callRouteAfter($route, $request, $response);\r\n\r\n\t\treturn $response;\r\n\t}\r\n<\/pre>\n<p>\u6ce8\u610f\u6b64\u51fd\u5f0f\u5167\u7684\u52d5\u4f5c\u8ddfdispatch\u6975\u5ea6\u96f7\u540c\u3002\u5dee\u5225\u5728\u65bc\u4e00\u500b\u662fglobal filter\u3001\u4e00\u500b\u662flocal filter(\u5dee\u5225\u4f55\u5728\uff1f\uff1f\uff1f)<br \/>\n<red><br \/>\n$route->run\u7684\u53c3\u6578$request\u662f\u591a\u9918\u7684\u3002<br \/>\n\u524d\u9762\u7684$route = $this->findRoute($request) \u5df2\u7d93\u662f\u50b3\u5165$request\u5f97\u5230\u7684\u7d50\u679c\uff0c\u6b64\u8655\u4e0d\u5fc5\u518d\u50b3\u4e00\u6b21\u3002<br \/>\n\u4e8b\u5be6\u4e0a\uff0crun\u51fd\u5f0f\u672c\u8eab\u7684\u5b9a\u7fa9\u6839\u672c\u6c92\u6709\u50b3\u5165\u53c3\u6578\u3002<br \/>\n\u53c3\u898b\uff1a<a href=\"https:\/\/blog.turn.tw\/?page_id=866\" title=\"\u57f7\u884c\u5de5\u4f5c\uff1aRouting\/Route.php\">\u57f7\u884c\u5de5\u4f5c\uff1aRouting\/Route.php<\/a><br \/>\n<\/red><\/p>\n<pre>\r\n\t\/**\r\n\t * Find the route matching a given request.\r\n\t *\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function findRoute($request)\r\n\t{\r\n\t\t$this->current = $route = $this->routes->match($request);\r\n\r\n\t\treturn $this->substituteBindings($route);\r\n\t}\r\n<\/pre>\n<p>\u9019\u4e0d\u662f\u55ae\u7d14\u6839\u64da$request\u53bb\u627e\u5230\u5c0d\u61c9$route\u7684\u51fd\u5f0f\u3002<br \/>\n\u5b83\u540c\u6642\u6703\u66f4\u65b0$this->current\u8b8a\u6578\u3001\u7528substituteBindings\u66f4\u65b0$route\u624d\u56de\u50b3\u3002<br \/>\n<red><br \/>\n\u82e5\u662f\u547d\u540d\u70bafindAndSetRoute\u6703\u4e0d\u6703\u66f4\u6e05\u695a\uff1f<br \/>\n<\/red><\/p>\n<pre>\r\n\t\/**\r\n\t * Substitute the route bindings onto the route.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tprotected function substituteBindings($route)\r\n\t{\r\n\t\tforeach ($route->parameters() as $key => $value)\r\n\t\t{\r\n\t\t\tif (isset($this->binders[$key]))\r\n\t\t\t{\r\n\t\t\t\t$route->setParameter($key, $this->performBinding($key, $value, $route));\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn $route;\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the binding callback for the given key.\r\n\t *\r\n\t * @param  string  $key\r\n\t * @param  string  $value\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @return mixed\r\n\t *\/\r\n\tprotected function performBinding($key, $value, $route)\r\n\t{\r\n\t\treturn call_user_func($this->binders[$key], $value, $route);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a route matched event listener.\r\n\t *\r\n\t * @param  string|callable  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function matched($callback)\r\n\t{\r\n\t\t$this->events->listen('router.matched', $callback);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new \"before\" filter with the router.\r\n\t *\r\n\t * @param  string|callable  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function before($callback)\r\n\t{\r\n\t\t$this->addGlobalFilter('before', $callback);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new \"after\" filter with the router.\r\n\t *\r\n\t * @param  string|callable  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function after($callback)\r\n\t{\r\n\t\t$this->addGlobalFilter('after', $callback);\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new global filter with the router.\r\n\t *\r\n\t * @param  string  $filter\r\n\t * @param  string|callable   $callback\r\n\t * @return void\r\n\t *\/\r\n\tprotected function addGlobalFilter($filter, $callback)\r\n\t{\r\n\t\t$this->events->listen('router.'.$filter, $this->parseFilter($callback));\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a new filter with the router.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @param  string|callable  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function filter($name, $callback)\r\n\t{\r\n\t\t$this->events->listen('router.filter: '.$name, $this->parseFilter($callback));\r\n\t}\r\n\r\n\t\/**\r\n\t * Parse the registered filter.\r\n\t *\r\n\t * @param  callable|string  $callback\r\n\t * @return mixed\r\n\t *\/\r\n\tprotected function parseFilter($callback)\r\n\t{\r\n\t\tif (is_string($callback) && ! str_contains($callback, '@'))\r\n\t\t{\r\n\t\t\treturn $callback.'@filter';\r\n\t\t}\r\n\r\n\t\treturn $callback;\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a pattern-based filter with the router.\r\n\t *\r\n\t * @param  string  $pattern\r\n\t * @param  string  $name\r\n\t * @param  array|null  $methods\r\n\t * @return void\r\n\t *\/\r\n\tpublic function when($pattern, $name, $methods = null)\r\n\t{\r\n\t\tif ( ! is_null($methods)) $methods = array_map('strtoupper', (array) $methods);\r\n\r\n\t\t$this->patternFilters[$pattern][] = compact('name', 'methods');\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a regular expression based filter with the router.\r\n\t *\r\n\t * @param  string     $pattern\r\n\t * @param  string     $name\r\n\t * @param  array|null $methods\r\n\t * @return void\r\n\t *\/\r\n\tpublic function whenRegex($pattern, $name, $methods = null)\r\n\t{\r\n\t\tif ( ! is_null($methods)) $methods = array_map('strtoupper', (array) $methods);\r\n\r\n\t\t$this->regexFilters[$pattern][] = compact('name', 'methods');\r\n\t}\r\n\r\n\t\/**\r\n\t * Register a model binder for a wildcard.\r\n\t *\r\n\t * @param  string  $key\r\n\t * @param  string  $class\r\n\t * @param  \\Closure  $callback\r\n\t * @return void\r\n\t *\r\n\t * @throws NotFoundHttpException\r\n\t *\/\r\n\tpublic function model($key, $class, Closure $callback = null)\r\n\t{\r\n\t\t$this->bind($key, function($value) use ($class, $callback)\r\n\t\t{\r\n\t\t\tif (is_null($value)) return null;\r\n\r\n\t\t\t\/\/ For model binders, we will attempt to retrieve the models using the find\r\n\t\t\t\/\/ method on the model instance. If we cannot retrieve the models we'll\r\n\t\t\t\/\/ throw a not found exception otherwise we will return the instance.\r\n\t\t\tif ($model = (new $class)->find($value))\r\n\t\t\t{\r\n\t\t\t\treturn $model;\r\n\t\t\t}\r\n\r\n\t\t\t\/\/ If a callback was supplied to the method we will call that to determine\r\n\t\t\t\/\/ what we should do when the model is not found. This just gives these\r\n\t\t\t\/\/ developer a little greater flexibility to decide what will happen.\r\n\t\t\tif ($callback instanceof Closure)\r\n\t\t\t{\r\n\t\t\t\treturn call_user_func($callback);\r\n\t\t\t}\r\n\r\n\t\t\tthrow new NotFoundHttpException;\r\n\t\t});\r\n\t}\r\n\r\n\t\/**\r\n\t * Add a new route parameter binder.\r\n\t *\r\n\t * @param  string  $key\r\n\t * @param  string|callable  $binder\r\n\t * @return void\r\n\t *\/\r\n\tpublic function bind($key, $binder)\r\n\t{\r\n\t\tif (is_string($binder))\r\n\t\t{\r\n\t\t\t$binder = $this->createClassBinding($binder);\r\n\t\t}\r\n\r\n\t\t$this->binders[str_replace('-', '_', $key)] = $binder;\r\n\t}\r\n\r\n\t\/**\r\n\t * Create a class based binding using the IoC container.\r\n\t *\r\n\t * @param  string    $binding\r\n\t * @return \\Closure\r\n\t *\/\r\n\tpublic function createClassBinding($binding)\r\n\t{\r\n\t\treturn function($value, $route) use ($binding)\r\n\t\t{\r\n\t\t\t\/\/ If the binding has an @ sign, we will assume it's being used to delimit\r\n\t\t\t\/\/ the class name from the bind method name. This allows for bindings\r\n\t\t\t\/\/ to run multiple bind methods in a single class for convenience.\r\n\t\t\t$segments = explode('@', $binding);\r\n\r\n\t\t\t$method = count($segments) == 2 ? $segments[1] : 'bind';\r\n\r\n\t\t\t$callable = [$this->container->make($segments[0]), $method];\r\n\r\n\t\t\treturn call_user_func($callable, $value, $route);\r\n\t\t};\r\n\t}\r\n\r\n\t\/**\r\n\t * Set a global where pattern on all routes\r\n\t *\r\n\t * @param  string  $key\r\n\t * @param  string  $pattern\r\n\t * @return void\r\n\t *\/\r\n\tpublic function pattern($key, $pattern)\r\n\t{\r\n\t\t$this->patterns[$key] = $pattern;\r\n\t}\r\n\r\n\t\/**\r\n\t * Set a group of global where patterns on all routes\r\n\t *\r\n\t * @param  array  $patterns\r\n\t * @return void\r\n\t *\/\r\n\tpublic function patterns($patterns)\r\n\t{\r\n\t\tforeach ($patterns as $key => $pattern)\r\n\t\t{\r\n\t\t\t$this->pattern($key, $pattern);\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the given filter with the request and response.\r\n\t *\r\n\t * @param  string  $filter\r\n\t * @param  \\Illuminate\\Http\\Request   $request\r\n\t * @param  \\Illuminate\\Http\\Response  $response\r\n\t * @return mixed\r\n\t *\/\r\n\tprotected function callFilter($filter, $request, $response = null)\r\n\t{\r\n\t\tif ( ! $this->filtering) return null;\r\n\r\n\t\treturn $this->events->until('router.'.$filter, array($request, $response));\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the given route's before filters.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return mixed\r\n\t *\/\r\n\tpublic function callRouteBefore($route, $request)\r\n\t{\r\n\t\t$response = $this->callPatternFilters($route, $request);\r\n\r\n\t\treturn $response ?: $this->callAttachedBefores($route, $request);\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the pattern based filters for the request.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return mixed|null\r\n\t *\/\r\n\tprotected function callPatternFilters($route, $request)\r\n\t{\r\n\t\tforeach ($this->findPatternFilters($request) as $filter => $parameters)\r\n\t\t{\r\n\t\t\t$response = $this->callRouteFilter($filter, $parameters, $route, $request);\r\n\r\n\t\t\tif ( ! is_null($response)) return $response;\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Find the patterned filters matching a request.\r\n\t *\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return array\r\n\t *\/\r\n\tpublic function findPatternFilters($request)\r\n\t{\r\n\t\t$results = array();\r\n\r\n\t\tlist($path, $method) = array($request->path(), $request->getMethod());\r\n\r\n\t\tforeach ($this->patternFilters as $pattern => $filters)\r\n\t\t{\r\n\t\t\t\/\/ To find the patterned middlewares for a request, we just need to check these\r\n\t\t\t\/\/ registered patterns against the path info for the current request to this\r\n\t\t\t\/\/ applications, and when it matches we will merge into these middlewares.\r\n\t\t\tif (str_is($pattern, $path))\r\n\t\t\t{\r\n\t\t\t\t$merge = $this->patternsByMethod($method, $filters);\r\n\r\n\t\t\t\t$results = array_merge($results, $merge);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tforeach ($this->regexFilters as $pattern => $filters)\r\n\t\t{\r\n\t\t\t\/\/ To find the patterned middlewares for a request, we just need to check these\r\n\t\t\t\/\/ registered patterns against the path info for the current request to this\r\n\t\t\t\/\/ applications, and when it matches we will merge into these middlewares.\r\n\t\t\tif (preg_match($pattern, $path))\r\n\t\t\t{\r\n\t\t\t\t$merge = $this->patternsByMethod($method, $filters);\r\n\r\n\t\t\t\t$results = array_merge($results, $merge);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn $results;\r\n\t}\r\n\r\n\t\/**\r\n\t * Filter pattern filters that don't apply to the request verb.\r\n\t *\r\n\t * @param  string  $method\r\n\t * @param  array   $filters\r\n\t * @return array\r\n\t *\/\r\n\tprotected function patternsByMethod($method, $filters)\r\n\t{\r\n\t\t$results = array();\r\n\r\n\t\tforeach ($filters as $filter)\r\n\t\t{\r\n\t\t\t\/\/ The idea here is to check and see if the pattern filter applies to this HTTP\r\n\t\t\t\/\/ request based on the request methods. Pattern filters might be limited by\r\n\t\t\t\/\/ the request verb to make it simply to assign to the given verb at once.\r\n\t\t\tif ($this->filterSupportsMethod($filter, $method))\r\n\t\t\t{\r\n\t\t\t\t$parsed = Route::parseFilters($filter['name']);\r\n\r\n\t\t\t\t$results = array_merge($results, $parsed);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn $results;\r\n\t}\r\n\r\n\t\/**\r\n\t * Determine if the given pattern filters applies to a given method.\r\n\t *\r\n\t * @param  array  $filter\r\n\t * @param  array  $method\r\n\t * @return bool\r\n\t *\/\r\n\tprotected function filterSupportsMethod($filter, $method)\r\n\t{\r\n\t\t$methods = $filter['methods'];\r\n\r\n\t\treturn (is_null($methods) || in_array($method, $methods));\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the given route's before (non-pattern) filters.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @return mixed\r\n\t *\/\r\n\tprotected function callAttachedBefores($route, $request)\r\n\t{\r\n\t\tforeach ($route->beforeFilters() as $filter => $parameters)\r\n\t\t{\r\n\t\t\t$response = $this->callRouteFilter($filter, $parameters, $route, $request);\r\n\r\n\t\t\tif ( ! is_null($response)) return $response;\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the given route's before filters.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @param  \\Illuminate\\Http\\Response  $response\r\n\t * @return mixed\r\n\t *\/\r\n\tpublic function callRouteAfter($route, $request, $response)\r\n\t{\r\n\t\tforeach ($route->afterFilters() as $filter => $parameters)\r\n\t\t{\r\n\t\t\t$this->callRouteFilter($filter, $parameters, $route, $request, $response);\r\n\t\t}\r\n\t}\r\n\r\n\t\/**\r\n\t * Call the given route filter.\r\n\t *\r\n\t * @param  string  $filter\r\n\t * @param  array  $parameters\r\n\t * @param  \\Illuminate\\Routing\\Route  $route\r\n\t * @param  \\Illuminate\\Http\\Request  $request\r\n\t * @param  \\Illuminate\\Http\\Response|null $response\r\n\t * @return mixed\r\n\t *\/\r\n\tpublic function callRouteFilter($filter, $parameters, $route, $request, $response = null)\r\n\t{\r\n\t\tif ( ! $this->filtering) return null;\r\n\r\n\t\t$data = array_merge(array($route, $request, $response), $parameters);\r\n\r\n\t\treturn $this->events->until('router.filter: '.$filter, $this->cleanFilterParameters($data));\r\n\t}\r\n\r\n\t\/**\r\n\t * Clean the parameters being passed to a filter callback.\r\n\t *\r\n\t * @param  array  $parameters\r\n\t * @return array\r\n\t *\/\r\n\tprotected function cleanFilterParameters(array $parameters)\r\n\t{\r\n\t\treturn array_filter($parameters, function($p)\r\n\t\t{\r\n\t\t\treturn ! is_null($p) && $p !== '';\r\n\t\t});\r\n\t}\r\n\r\n\t\/**\r\n\t * Create a response instance from the given value.\r\n\t *\r\n\t * @param  \\Symfony\\Component\\HttpFoundation\\Request  $request\r\n\t * @param  mixed  $response\r\n\t * @return \\Illuminate\\Http\\Response\r\n\t *\/\r\n\tprotected function prepareResponse($request, $response)\r\n\t{\r\n\t\tif ( ! $response instanceof SymfonyResponse)\r\n\t\t{\r\n\t\t\t$response = new Response($response);\r\n\t\t}\r\n\r\n\t\treturn $response->prepare($request);\r\n\t}\r\n\r\n\t\/**\r\n\t * Run a callback with filters disable on the router.\r\n\t *\r\n\t * @param  callable  $callback\r\n\t * @return void\r\n\t *\/\r\n\tpublic function withoutFilters(callable $callback)\r\n\t{\r\n\t\t$this->disableFilters();\r\n\r\n\t\tcall_user_func($callback);\r\n\r\n\t\t$this->enableFilters();\r\n\t}\r\n\r\n\t\/**\r\n\t * Enable route filtering on the router.\r\n\t *\r\n\t * @return void\r\n\t *\/\r\n\tpublic function enableFilters()\r\n\t{\r\n\t\t$this->filtering = true;\r\n\t}\r\n\r\n\t\/**\r\n\t * Disable route filtering on the router.\r\n\t *\r\n\t * @return void\r\n\t *\/\r\n\tpublic function disableFilters()\r\n\t{\r\n\t\t$this->filtering = false;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get a route parameter for the current route.\r\n\t *\r\n\t * @param  string  $key\r\n\t * @param  string  $default\r\n\t * @return mixed\r\n\t *\/\r\n\tpublic function input($key, $default = null)\r\n\t{\r\n\t\treturn $this->current()->parameter($key, $default);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the currently dispatched route instance.\r\n\t *\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function getCurrentRoute()\r\n\t{\r\n\t\treturn $this->current();\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the currently dispatched route instance.\r\n\t *\r\n\t * @return \\Illuminate\\Routing\\Route\r\n\t *\/\r\n\tpublic function current()\r\n\t{\r\n\t\treturn $this->current;\r\n\t}\r\n\r\n\t\/**\r\n\t * Check if a route with the given name exists.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @return bool\r\n\t *\/\r\n\tpublic function has($name)\r\n\t{\r\n\t\treturn $this->routes->hasNamedRoute($name);\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the current route name.\r\n\t *\r\n\t * @return string|null\r\n\t *\/\r\n\tpublic function currentRouteName()\r\n\t{\r\n\t\treturn ($this->current()) ? $this->current()->getName() : null;\r\n\t}\r\n\r\n\t\/**\r\n\t * Alias for the \"currentRouteNamed\" method.\r\n\t *\r\n\t * @param  mixed  string\r\n\t * @return bool\r\n\t *\/\r\n\tpublic function is()\r\n\t{\r\n\t\tforeach (func_get_args() as $pattern)\r\n\t\t{\r\n\t\t\tif (str_is($pattern, $this->currentRouteName()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\t\/**\r\n\t * Determine if the current route matches a given name.\r\n\t *\r\n\t * @param  string  $name\r\n\t * @return bool\r\n\t *\/\r\n\tpublic function currentRouteNamed($name)\r\n\t{\r\n\t\treturn ($this->current()) ? $this->current()->getName() == $name : false;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the current route action.\r\n\t *\r\n\t * @return string|null\r\n\t *\/\r\n\tpublic function currentRouteAction()\r\n\t{\r\n\t\tif ( ! $this->current()) return;\r\n\r\n\t\t$action = $this->current()->getAction();\r\n\r\n\t\treturn isset($action['controller']) ? $action['controller'] : null;\r\n\t}\r\n\r\n\t\/**\r\n\t * Alias for the \"currentRouteUses\" method.\r\n\t *\r\n\t * @param  mixed  string\r\n\t * @return bool\r\n\t *\/\r\n\tpublic function uses()\r\n\t{\r\n\t\tforeach (func_get_args() as $pattern)\r\n\t\t{\r\n\t\t\tif (str_is($pattern, $this->currentRouteAction()))\r\n\t\t\t{\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn false;\r\n\t}\r\n\r\n\t\/**\r\n\t * Determine if the current route action matches a given action.\r\n\t *\r\n\t * @param  string  $action\r\n\t * @return bool\r\n\t *\/\r\n\tpublic function currentRouteUses($action)\r\n\t{\r\n\t\treturn $this->currentRouteAction() == $action;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the request currently being dispatched.\r\n\t *\r\n\t * @return \\Illuminate\\Http\\Request\r\n\t *\/\r\n\tpublic function getCurrentRequest()\r\n\t{\r\n\t\treturn $this->currentRequest;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the underlying route collection.\r\n\t *\r\n\t * @return \\Illuminate\\Routing\\RouteCollection\r\n\t *\/\r\n\tpublic function getRoutes()\r\n\t{\r\n\t\treturn $this->routes;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the controller dispatcher instance.\r\n\t *\r\n\t * @return \\Illuminate\\Routing\\ControllerDispatcher\r\n\t *\/\r\n\tpublic function getControllerDispatcher()\r\n\t{\r\n\t\tif (is_null($this->controllerDispatcher))\r\n\t\t{\r\n\t\t\t$this->controllerDispatcher = new ControllerDispatcher($this, $this->container);\r\n\t\t}\r\n\r\n\t\treturn $this->controllerDispatcher;\r\n\t}\r\n\r\n\t\/**\r\n\t * Set the controller dispatcher instance.\r\n\t *\r\n\t * @param  \\Illuminate\\Routing\\ControllerDispatcher  $dispatcher\r\n\t * @return void\r\n\t *\/\r\n\tpublic function setControllerDispatcher(ControllerDispatcher $dispatcher)\r\n\t{\r\n\t\t$this->controllerDispatcher = $dispatcher;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get a controller inspector instance.\r\n\t *\r\n\t * @return \\Illuminate\\Routing\\ControllerInspector\r\n\t *\/\r\n\tpublic function getInspector()\r\n\t{\r\n\t\treturn $this->inspector ?: $this->inspector = new ControllerInspector;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the global \"where\" patterns.\r\n\t *\r\n\t * @return array\r\n\t *\/\r\n\tpublic function getPatterns()\r\n\t{\r\n\t\treturn $this->patterns;\r\n\t}\r\n\r\n\t\/**\r\n\t * Get the response for a given request.\r\n\t *\r\n\t * @param  \\Symfony\\Component\\HttpFoundation\\Request  $request\r\n\t * @param  int   $type\r\n\t * @param  bool  $catch\r\n\t * @return \\Illuminate\\Http\\Response\r\n\t *\/\r\n\tpublic function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)\r\n\t{\r\n\t\treturn $this->dispatch(Request::createFromBase($request));\r\n\t}\r\n\r\n}\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u8207routing\u76f8\u95dc\u7684\u4e00\u5207\u90fd\u900f\u904e\u6b64Router\u985e\u5225\u5b8c\u6210\u3002 \u7531\u65bcLaravel\u652f\u63f4\u7684routing\u65b9\u5f0f\u975e\u5e38\u591a\u5143\uff0c &hellip; <a href=\"https:\/\/blog.turn.tw\/?page_id=838\" class=\"more-link\">\u7e7c\u7e8c\u95b1\u8b80 <span class=\"screen-reader-text\">\u5206\u914d\u5de5\u4f5c\uff1aRouting\/Router.php<\/span> <span class=\"meta-nav\">&rarr;<\/span> <\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"_mi_skip_tracking":false},"_links":{"self":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/pages\/838"}],"collection":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=838"}],"version-history":[{"count":17,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/pages\/838\/revisions"}],"predecessor-version":[{"id":903,"href":"https:\/\/blog.turn.tw\/index.php?rest_route=\/wp\/v2\/pages\/838\/revisions\/903"}],"wp:attachment":[{"href":"https:\/\/blog.turn.tw\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=838"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}