RouteCollection.php
TLDR
This file, RouteCollection.php
, is a part of the Illuminate Routing component of the Laravel framework. It defines a class RouteCollection
that manages a collection of routes. The class provides methods for adding routes, retrieving routes based on various criteria, and performing lookups based on route names or controller actions.
Methods
add
This method adds a Route
instance to the collection. It adds the route to the internal arrays used for method-based and all routes lookup.
addToCollections
This method adds the given route to the arrays of routes. It adds the route to the method-based routing array and the all routes array.
addLookups
This method adds the route to the lookup tables if necessary. If the route has a name, it adds it to the name lookup table. If the route is routed to a controller, it adds the action and route pair to the action lookup table.
addToActionList
This method adds a route to the controller action dictionary. It adds the specified action and route pair to the action lookup table.
refreshNameLookups
This method refreshes the name lookup table. It clears the existing name lookup table and rebuilds it by iterating through all the routes in the collection.
refreshActionLookups
This method refreshes the action lookup table. It clears the existing action lookup table and rebuilds it by iterating through all the routes in the collection.
match
This method finds the first route that matches the given request. It gets the routes for the specified request method and then matches the request against those routes. It returns the matched route or throws exceptions if no matching route is found.
get
This method retrieves routes from the collection based on the specified method. If no method is provided, it returns all routes. Otherwise, it returns the routes for the specified method.
hasNamedRoute
This method determines if the route collection contains a route with the specified name. It returns true
if a matching named route is found; otherwise, returns false
.
getByName
This method retrieves a route instance by its name. It returns the route corresponding to the specified name or null
if no matching named route is found.
getByAction
This method retrieves a route instance by its controller action. It returns the route corresponding to the specified action or null
if no matching route is found.
getRoutes
This method retrieves all routes in the collection. It returns an array of Route
instances.
getRoutesByMethod
This method retrieves all routes in the collection and organizes them by their HTTP verb or method. It returns an array where the keys are the methods and the values are arrays of routes.
getRoutesByName
This method retrieves all routes in the collection and organizes them by their name. It returns an array where the keys are the names and the values are routes.
toSymfonyRouteCollection
This method converts the collection to an instance of the Symfony RouteCollection
class. It first calls the parent class's toSymfonyRouteCollection
method to get the Symfony routes and then refreshes the name lookup table. It returns the Symfony route collection.
toCompiledRouteCollection
This method converts the collection to an instance of the CompiledRouteCollection
class. It compiles the routes using the compile
method, creates a new CompiledRouteCollection
instance with the compiled routes and their attributes, and sets the router and container on the new instance. It returns the compiled route collection.
Class
This file defines a single class, RouteCollection
, which manages a collection of routes. The class extends the AbstractRouteCollection
class and provides methods for adding and retrieving routes, as well as performing various lookups.
<?php
namespace Illuminate\Routing;
use Illuminate\Container\Container;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
class RouteCollection extends AbstractRouteCollection
{
/**
* An array of the routes keyed by method.
*
* @var array
*/
protected $routes = [];
/**
* A flattened array of all of the routes.
*
* @var \Illuminate\Routing\Route[]
*/
protected $allRoutes = [];
/**
* A look-up table of routes by their names.
*
* @var \Illuminate\Routing\Route[]
*/
protected $nameList = [];
/**
* A look-up table of routes by controller action.
*
* @var \Illuminate\Routing\Route[]
*/
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->getDomain().$route->uri();
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.
if ($name = $route->getName()) {
$this->nameList[$name] = $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.
$action = $route->getAction();
if (isset($action['controller'])) {
$this->addToActionList($action, $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;
}
/**
* Refresh the name look-up table.
*
* This is done in case any names are fluently defined or if routes are overwritten.
*
* @return void
*/
public function refreshNameLookups()
{
$this->nameList = [];
foreach ($this->allRoutes as $route) {
if ($route->getName()) {
$this->nameList[$route->getName()] = $route;
}
}
}
/**
* Refresh the action look-up table.
*
* This is done in case any actions are overwritten with new controllers.
*
* @return void
*/
public function refreshActionLookups()
{
$this->actionList = [];
foreach ($this->allRoutes as $route) {
if (isset($route->getAction()['controller'])) {
$this->addToActionList($route->getAction(), $route);
}
}
}
/**
* Find the first route matching a given request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Routing\Route
*
* @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
* @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->matchAgainstRoutes($routes, $request);
return $this->handleMatchedRoute($request, $route);
}
/**
* Get routes from the collection by method.
*
* @param string|null $method
* @return \Illuminate\Routing\Route[]
*/
public function get($method = null)
{
return is_null($method) ? $this->getRoutes() : 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 $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 $this->actionList[$action] ?? null;
}
/**
* Get all of the routes in the collection.
*
* @return \Illuminate\Routing\Route[]
*/
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 all of the routes keyed by their name.
*
* @return \Illuminate\Routing\Route[]
*/
public function getRoutesByName()
{
return $this->nameList;
}
/**
* Convert the collection to a Symfony RouteCollection instance.
*
* @return \Symfony\Component\Routing\RouteCollection
*/
public function toSymfonyRouteCollection()
{
$symfonyRoutes = parent::toSymfonyRouteCollection();
$this->refreshNameLookups();
return $symfonyRoutes;
}
/**
* Convert the collection to a CompiledRouteCollection instance.
*
* @param \Illuminate\Routing\Router $router
* @param \Illuminate\Container\Container $container
* @return \Illuminate\Routing\CompiledRouteCollection
*/
public function toCompiledRouteCollection(Router $router, Container $container)
{
['compiled' => $compiled, 'attributes' => $attributes] = $this->compile();
return (new CompiledRouteCollection($compiled, $attributes))
->setRouter($router)
->setContainer($container);
}
}