CompiledRouteCollection.php
TLDR
The CompiledRouteCollection
file in the Illuminate\Routing
namespace is a class that extends the AbstractRouteCollection
class. It represents a collection of compiled routes. It is used internally in the Laravel framework for route matching and handling.
Methods
__construct
The constructor method of the CompiledRouteCollection
class. It initializes the $compiled
and $attributes
properties.
add
Adds a Route
instance to the collection.
refreshNameLookups
Refreshes the name look-up table for the routes.
refreshActionLookups
Refreshes the action look-up table for the routes.
match
Finds the first route in the collection that matches the given request. It uses a CompiledUrlMatcher
instance to match the request against the compiled routes.
requestWithoutTrailingSlash
Returns a cloned instance of the given request without any trailing slash on the URI.
get
Returns an array of routes from the collection based on the given HTTP method. If no method is provided, it returns all routes.
hasNamedRoute
Checks if the route collection contains a route with the given name.
getByName
Returns a route instance by its name.
getByAction
Returns a route instance by its controller action.
getRoutes
Returns all the routes in the collection.
getRoutesByMethod
Returns all the routes in the collection grouped by their HTTP verb/method.
getRoutesByName
Returns all the routes in the collection keyed by their name.
newRoute
Resolves an array of attributes to a Route instance.
setRouter
Sets the router instance on the route.
setContainer
Sets the container instance on the route.
Classes
There are no classes in this file.
<?php
namespace Illuminate\Routing;
use Illuminate\Container\Container;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Exception\MethodNotAllowedException;
use Symfony\Component\Routing\Exception\ResourceNotFoundException;
use Symfony\Component\Routing\Matcher\CompiledUrlMatcher;
use Symfony\Component\Routing\RequestContext;
class CompiledRouteCollection extends AbstractRouteCollection
{
/**
* The compiled routes collection.
*
* @var array
*/
protected $compiled = [];
/**
* An array of the route attributes keyed by name.
*
* @var array
*/
protected $attributes = [];
/**
* The dynamically added routes that were added after loading the cached, compiled routes.
*
* @var \Illuminate\Routing\RouteCollection|null
*/
protected $routes;
/**
* The router instance used by the route.
*
* @var \Illuminate\Routing\Router
*/
protected $router;
/**
* The container instance used by the route.
*
* @var \Illuminate\Container\Container
*/
protected $container;
/**
* Create a new CompiledRouteCollection instance.
*
* @param array $compiled
* @param array $attributes
* @return void
*/
public function __construct(array $compiled, array $attributes)
{
$this->compiled = $compiled;
$this->attributes = $attributes;
$this->routes = new RouteCollection;
}
/**
* Add a Route instance to the collection.
*
* @param \Illuminate\Routing\Route $route
* @return \Illuminate\Routing\Route
*/
public function add(Route $route)
{
return $this->routes->add($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()
{
//
}
/**
* Refresh the action look-up table.
*
* This is done in case any actions are overwritten with new controllers.
*
* @return void
*/
public function refreshActionLookups()
{
//
}
/**
* 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)
{
$matcher = new CompiledUrlMatcher(
$this->compiled, (new RequestContext)->fromRequest(
$trimmedRequest = $this->requestWithoutTrailingSlash($request)
)
);
$route = null;
try {
if ($result = $matcher->matchRequest($trimmedRequest)) {
$route = $this->getByName($result['_route']);
}
} catch (ResourceNotFoundException|MethodNotAllowedException) {
try {
return $this->routes->match($request);
} catch (NotFoundHttpException) {
//
}
}
if ($route && $route->isFallback) {
try {
$dynamicRoute = $this->routes->match($request);
if (! $dynamicRoute->isFallback) {
$route = $dynamicRoute;
}
} catch (NotFoundHttpException|MethodNotAllowedHttpException) {
//
}
}
return $this->handleMatchedRoute($request, $route);
}
/**
* Get a cloned instance of the given request without any trailing slash on the URI.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Request
*/
protected function requestWithoutTrailingSlash(Request $request)
{
$trimmedRequest = $request->duplicate();
$parts = explode('?', $request->server->get('REQUEST_URI'), 2);
$trimmedRequest->server->set(
'REQUEST_URI', rtrim($parts[0], '/').(isset($parts[1]) ? '?'.$parts[1] : '')
);
return $trimmedRequest;
}
/**
* Get routes from the collection by method.
*
* @param string|null $method
* @return \Illuminate\Routing\Route[]
*/
public function get($method = null)
{
return $this->getRoutesByMethod()[$method] ?? [];
}
/**
* Determine if the route collection contains a given named route.
*
* @param string $name
* @return bool
*/
public function hasNamedRoute($name)
{
return isset($this->attributes[$name]) || $this->routes->hasNamedRoute($name);
}
/**
* Get a route instance by its name.
*
* @param string $name
* @return \Illuminate\Routing\Route|null
*/
public function getByName($name)
{
if (isset($this->attributes[$name])) {
return $this->newRoute($this->attributes[$name]);
}
return $this->routes->getByName($name);
}
/**
* Get a route instance by its controller action.
*
* @param string $action
* @return \Illuminate\Routing\Route|null
*/
public function getByAction($action)
{
$attributes = collect($this->attributes)->first(function (array $attributes) use ($action) {
if (isset($attributes['action']['controller'])) {
return trim($attributes['action']['controller'], '\\') === $action;
}
return $attributes['action']['uses'] === $action;
});
if ($attributes) {
return $this->newRoute($attributes);
}
return $this->routes->getByAction($action);
}
/**
* Get all of the routes in the collection.
*
* @return \Illuminate\Routing\Route[]
*/
public function getRoutes()
{
return collect($this->attributes)
->map(function (array $attributes) {
return $this->newRoute($attributes);
})
->merge($this->routes->getRoutes())
->values()
->all();
}
/**
* Get all of the routes keyed by their HTTP verb / method.
*
* @return array
*/
public function getRoutesByMethod()
{
return collect($this->getRoutes())
->groupBy(function (Route $route) {
return $route->methods();
})
->map(function (Collection $routes) {
return $routes->mapWithKeys(function (Route $route) {
return [$route->getDomain().$route->uri => $route];
})->all();
})
->all();
}
/**
* Get all of the routes keyed by their name.
*
* @return \Illuminate\Routing\Route[]
*/
public function getRoutesByName()
{
return collect($this->getRoutes())
->keyBy(function (Route $route) {
return $route->getName();
})
->all();
}
/**
* Resolve an array of attributes to a Route instance.
*
* @param array $attributes
* @return \Illuminate\Routing\Route
*/
protected function newRoute(array $attributes)
{
if (empty($attributes['action']['prefix'] ?? '')) {
$baseUri = $attributes['uri'];
} else {
$prefix = trim($attributes['action']['prefix'], '/');
$baseUri = trim(implode(
'/', array_slice(
explode('/', trim($attributes['uri'], '/')),
count($prefix !== '' ? explode('/', $prefix) : [])
)
), '/');
}
return $this->router->newRoute($attributes['methods'], $baseUri === '' ? '/' : $baseUri, $attributes['action'])
->setFallback($attributes['fallback'])
->setDefaults($attributes['defaults'])
->setWheres($attributes['wheres'])
->setBindingFields($attributes['bindingFields'])
->block($attributes['lockSeconds'] ?? null, $attributes['waitSeconds'] ?? null)
->withTrashed($attributes['withTrashed'] ?? false);
}
/**
* Set the router instance on the route.
*
* @param \Illuminate\Routing\Router $router
* @return $this
*/
public function setRouter(Router $router)
{
$this->router = $router;
return $this;
}
/**
* Set the container instance on the route.
*
* @param \Illuminate\Container\Container $container
* @return $this
*/
public function setContainer(Container $container)
{
$this->container = $container;
return $this;
}
}