Viewing file: RouteCollection.php (8.54 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
<?php
namespace Illuminate\Routing;
use Countable; use ArrayIterator; use IteratorAggregate; use Illuminate\Support\Arr; use Illuminate\Http\Request; use Illuminate\Http\Response; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
class RouteCollection implements Countable, IteratorAggregate { /** * An array of the routes keyed by method. * * @var array */ protected $routes = [];
/** * An flattened array of all of the routes. * * @var array */ protected $allRoutes = [];
/** * A look-up table of routes by their names. * * @var array */ protected $nameList = [];
/** * A look-up table of routes by controller action. * * @var array */ protected $actionList = [];
/** * Add a Route instance to the collection. * * @param \Illuminate\Routing\Route $route * @return \Illuminate\Routing\Route */ public function add(Route $route) { $this->addToCollections($route);
$this->addLookups($route);
return $route; }
/** * Add the given route to the arrays of routes. * * @param \Illuminate\Routing\Route $route * @return void */ protected function addToCollections($route) { $domainAndUri = $route->domain().$route->getUri();
foreach ($route->methods() as $method) { $this->routes[$method][$domainAndUri] = $route; }
$this->allRoutes[$method.$domainAndUri] = $route; }
/** * Add the route to any look-up tables if necessary. * * @param \Illuminate\Routing\Route $route * @return void */ protected function addLookups($route) { // If the route has a name, we will add it to the name look-up table so that we // will quickly be able to find any route associate with a name and not have // to iterate through every route every time we need to perform a look-up. $action = $route->getAction();
if (isset($action['as'])) { $this->nameList[$action['as']] = $route; }
// When the route is routing to a controller we will also store the action that // is used by the route. This will let us reverse route to controllers while // processing a request and easily generate URLs to the given controllers. if (isset($action['controller'])) { $this->addToActionList($action, $route); } }
/** * Refresh the name look-up table. * * This is done in case any names are fluently defined. * * @return void */ public function refreshNameLookups() { $this->nameList = [];
foreach ($this->allRoutes as $route) { if ($route->getName()) { $this->nameList[$route->getName()] = $route; } } }
/** * Add a route to the controller action dictionary. * * @param array $action * @param \Illuminate\Routing\Route $route * @return void */ protected function addToActionList($action, $route) { $this->actionList[trim($action['controller'], '\\')] = $route; }
/** * Find the first route matching a given request. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException */ public function match(Request $request) { $routes = $this->get($request->getMethod());
// First, we will see if we can find a matching route for this current request // method. If we can, great, we can just return it so that it can be called // by the consumer. Otherwise we will check for routes with another verb. $route = $this->check($routes, $request);
if (! is_null($route)) { return $route->bind($request); }
// If no route was found we will now check if a matching route is specified by // another HTTP verb. If it is we will need to throw a MethodNotAllowed and // inform the user agent of which HTTP verb it should use for this route. $others = $this->checkForAlternateVerbs($request);
if (count($others) > 0) { return $this->getRouteForMethods($request, $others); }
throw new NotFoundHttpException; }
/** * Determine if any routes match on another HTTP verb. * * @param \Illuminate\Http\Request $request * @return array */ protected function checkForAlternateVerbs($request) { $methods = array_diff(Router::$verbs, [$request->getMethod()]);
// Here we will spin through all verbs except for the current request verb and // check to see if any routes respond to them. If they do, we will return a // proper error response with the correct headers on the response string. $others = [];
foreach ($methods as $method) { if (! is_null($this->check($this->get($method), $request, false))) { $others[] = $method; } }
return $others; }
/** * Get a route (if necessary) that responds when other available methods are present. * * @param \Illuminate\Http\Request $request * @param array $methods * @return \Illuminate\Routing\Route * * @throws \Symfony\Component\Routing\Exception\MethodNotAllowedHttpException */ protected function getRouteForMethods($request, array $methods) { if ($request->method() == 'OPTIONS') { return (new Route('OPTIONS', $request->path(), function () use ($methods) { return new Response('', 200, ['Allow' => implode(',', $methods)]); }))->bind($request); }
$this->methodNotAllowed($methods); }
/** * Throw a method not allowed HTTP exception. * * @param array $others * @return void * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException */ protected function methodNotAllowed(array $others) { throw new MethodNotAllowedHttpException($others); }
/** * Determine if a route in the array matches the request. * * @param array $routes * @param \Illuminate\http\Request $request * @param bool $includingMethod * @return \Illuminate\Routing\Route|null */ protected function check(array $routes, $request, $includingMethod = true) { return Arr::first($routes, function ($key, $value) use ($request, $includingMethod) { return $value->matches($request, $includingMethod); }); }
/** * Get all of the routes in the collection. * * @param string|null $method * @return array */ public function get($method = null) { if (is_null($method)) { return $this->getRoutes(); }
return Arr::get($this->routes, $method, []); }
/** * Determine if the route collection contains a given named route. * * @param string $name * @return bool */ public function hasNamedRoute($name) { return ! is_null($this->getByName($name)); }
/** * Get a route instance by its name. * * @param string $name * @return \Illuminate\Routing\Route|null */ public function getByName($name) { return isset($this->nameList[$name]) ? $this->nameList[$name] : null; }
/** * Get a route instance by its controller action. * * @param string $action * @return \Illuminate\Routing\Route|null */ public function getByAction($action) { return isset($this->actionList[$action]) ? $this->actionList[$action] : null; }
/** * Get all of the routes in the collection. * * @return array */ public function getRoutes() { return array_values($this->allRoutes); }
/** * Get all of the routes keyed by their HTTP verb / method. * * @return array */ public function getRoutesByMethod() { return $this->routes; }
/** * Get an iterator for the items. * * @return \ArrayIterator */ public function getIterator() { return new ArrayIterator($this->getRoutes()); }
/** * Count the number of items in the collection. * * @return int */ public function count() { return count($this->getRoutes()); } }
|