Blame | Letzte Änderung | Log anzeigen | RSS feed
<?phpnamespace Illuminate\Routing;use ArrayObject;use Closure;use Illuminate\Container\Container;use Illuminate\Contracts\Events\Dispatcher;use Illuminate\Contracts\Routing\BindingRegistrar;use Illuminate\Contracts\Routing\Registrar as RegistrarContract;use Illuminate\Contracts\Support\Arrayable;use Illuminate\Contracts\Support\Jsonable;use Illuminate\Contracts\Support\Responsable;use Illuminate\Database\Eloquent\Model;use Illuminate\Http\JsonResponse;use Illuminate\Http\Request;use Illuminate\Http\Response;use Illuminate\Routing\Events\RouteMatched;use Illuminate\Routing\Events\Routing;use Illuminate\Support\Arr;use Illuminate\Support\Collection;use Illuminate\Support\Str;use Illuminate\Support\Stringable;use Illuminate\Support\Traits\Macroable;use JsonSerializable;use Psr\Http\Message\ResponseInterface as PsrResponseInterface;use ReflectionClass;use stdClass;use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory;use Symfony\Component\HttpFoundation\Response as SymfonyResponse;/*** @mixin \Illuminate\Routing\RouteRegistrar*/class Router implements BindingRegistrar, RegistrarContract{use Macroable {__call as macroCall;}/*** The event dispatcher instance.** @var \Illuminate\Contracts\Events\Dispatcher*/protected $events;/*** The IoC container instance.** @var \Illuminate\Container\Container*/protected $container;/*** The route collection instance.** @var \Illuminate\Routing\RouteCollectionInterface*/protected $routes;/*** The currently dispatched route instance.** @var \Illuminate\Routing\Route|null*/protected $current;/*** The request currently being dispatched.** @var \Illuminate\Http\Request*/protected $currentRequest;/*** All of the short-hand keys for middlewares.** @var array*/protected $middleware = [];/*** All of the middleware groups.** @var array*/protected $middlewareGroups = [];/*** The priority-sorted list of middleware.** Forces the listed middleware to always be in the given order.** @var array*/public $middlewarePriority = [];/*** The registered route value binders.** @var array*/protected $binders = [];/*** The globally available parameter patterns.** @var array*/protected $patterns = [];/*** The route group attribute stack.** @var array*/protected $groupStack = [];/*** All of the verbs supported by the router.** @var string[]*/public static $verbs = ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'];/*** Create a new Router instance.** @param \Illuminate\Contracts\Events\Dispatcher $events* @param \Illuminate\Container\Container|null $container* @return void*/public function __construct(Dispatcher $events, Container $container = null){$this->events = $events;$this->routes = new RouteCollection;$this->container = $container ?: new Container;}/*** Register a new GET route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function get($uri, $action = null){return $this->addRoute(['GET', 'HEAD'], $uri, $action);}/*** Register a new POST route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function post($uri, $action = null){return $this->addRoute('POST', $uri, $action);}/*** Register a new PUT route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function put($uri, $action = null){return $this->addRoute('PUT', $uri, $action);}/*** Register a new PATCH route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function patch($uri, $action = null){return $this->addRoute('PATCH', $uri, $action);}/*** Register a new DELETE route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function delete($uri, $action = null){return $this->addRoute('DELETE', $uri, $action);}/*** Register a new OPTIONS route with the router.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function options($uri, $action = null){return $this->addRoute('OPTIONS', $uri, $action);}/*** Register a new route responding to all verbs.** @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function any($uri, $action = null){return $this->addRoute(self::$verbs, $uri, $action);}/*** Register a new Fallback route with the router.** @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function fallback($action){$placeholder = 'fallbackPlaceholder';return $this->addRoute('GET', "{{$placeholder}}", $action)->where($placeholder, '.*')->fallback();}/*** Create a redirect from one URI to another.** @param string $uri* @param string $destination* @param int $status* @return \Illuminate\Routing\Route*/public function redirect($uri, $destination, $status = 302){return $this->any($uri, '\Illuminate\Routing\RedirectController')->defaults('destination', $destination)->defaults('status', $status);}/*** Create a permanent redirect from one URI to another.** @param string $uri* @param string $destination* @return \Illuminate\Routing\Route*/public function permanentRedirect($uri, $destination){return $this->redirect($uri, $destination, 301);}/*** Register a new route that returns a view.** @param string $uri* @param string $view* @param array $data* @param int|array $status* @param array $headers* @return \Illuminate\Routing\Route*/public function view($uri, $view, $data = [], $status = 200, array $headers = []){return $this->match(['GET', 'HEAD'], $uri, '\Illuminate\Routing\ViewController')->setDefaults(['view' => $view,'data' => $data,'status' => is_array($status) ? 200 : $status,'headers' => is_array($status) ? $status : $headers,]);}/*** Register a new route with the given verbs.** @param array|string $methods* @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function match($methods, $uri, $action = null){return $this->addRoute(array_map('strtoupper', (array) $methods), $uri, $action);}/*** Register an array of resource controllers.** @param array $resources* @param array $options* @return void*/public function resources(array $resources, array $options = []){foreach ($resources as $name => $controller) {$this->resource($name, $controller, $options);}}/*** Route a resource to a controller.** @param string $name* @param string $controller* @param array $options* @return \Illuminate\Routing\PendingResourceRegistration*/public function resource($name, $controller, array $options = []){if ($this->container && $this->container->bound(ResourceRegistrar::class)) {$registrar = $this->container->make(ResourceRegistrar::class);} else {$registrar = new ResourceRegistrar($this);}return new PendingResourceRegistration($registrar, $name, $controller, $options);}/*** Register an array of API resource controllers.** @param array $resources* @param array $options* @return void*/public function apiResources(array $resources, array $options = []){foreach ($resources as $name => $controller) {$this->apiResource($name, $controller, $options);}}/*** Route an API resource to a controller.** @param string $name* @param string $controller* @param array $options* @return \Illuminate\Routing\PendingResourceRegistration*/public function apiResource($name, $controller, array $options = []){$only = ['index', 'show', 'store', 'update', 'destroy'];if (isset($options['except'])) {$only = array_diff($only, (array) $options['except']);}return $this->resource($name, $controller, array_merge(['only' => $only,], $options));}/*** Register an array of singleton resource controllers.** @param array $singletons* @param array $options* @return void*/public function singletons(array $singletons, array $options = []){foreach ($singletons as $name => $controller) {$this->singleton($name, $controller, $options);}}/*** Route a singleton resource to a controller.** @param string $name* @param string $controller* @param array $options* @return \Illuminate\Routing\PendingSingletonResourceRegistration*/public function singleton($name, $controller, array $options = []){if ($this->container && $this->container->bound(ResourceRegistrar::class)) {$registrar = $this->container->make(ResourceRegistrar::class);} else {$registrar = new ResourceRegistrar($this);}return new PendingSingletonResourceRegistration($registrar, $name, $controller, $options);}/*** Register an array of API singleton resource controllers.** @param array $singletons* @param array $options* @return void*/public function apiSingletons(array $singletons, array $options = []){foreach ($singletons as $name => $controller) {$this->apiSingleton($name, $controller, $options);}}/*** Route an API singleton resource to a controller.** @param string $name* @param string $controller* @param array $options* @return \Illuminate\Routing\PendingSingletonResourceRegistration*/public function apiSingleton($name, $controller, array $options = []){$only = ['show', 'update', 'destroy'];if (isset($options['except'])) {$only = array_diff($only, (array) $options['except']);}return $this->singleton($name, $controller, array_merge(['only' => $only,'apiSingleton' => true,], $options));}/*** Create a route group with shared attributes.** @param array $attributes* @param \Closure|array|string $routes* @return $this*/public function group(array $attributes, $routes){foreach (Arr::wrap($routes) as $groupRoutes) {$this->updateGroupStack($attributes);// Once we have updated the group stack, we'll load the provided routes and// merge in the group's attributes when the routes are created. After we// have created the routes, we will pop the attributes off the stack.$this->loadRoutes($groupRoutes);array_pop($this->groupStack);}return $this;}/*** Update the group stack with the given attributes.** @param array $attributes* @return void*/protected function updateGroupStack(array $attributes){if ($this->hasGroupStack()) {$attributes = $this->mergeWithLastGroup($attributes);}$this->groupStack[] = $attributes;}/*** Merge the given array with the last group stack.** @param array $new* @param bool $prependExistingPrefix* @return array*/public function mergeWithLastGroup($new, $prependExistingPrefix = true){return RouteGroup::merge($new, end($this->groupStack), $prependExistingPrefix);}/*** Load the provided routes.** @param \Closure|string $routes* @return void*/protected function loadRoutes($routes){if ($routes instanceof Closure) {$routes($this);} else {(new RouteFileRegistrar($this))->register($routes);}}/*** Get the prefix from the last group on the stack.** @return string*/public function getLastGroupPrefix(){if ($this->hasGroupStack()) {$last = end($this->groupStack);return $last['prefix'] ?? '';}return '';}/*** Add a route to the underlying route collection.** @param array|string $methods* @param string $uri* @param array|string|callable|null $action* @return \Illuminate\Routing\Route*/public function addRoute($methods, $uri, $action){return $this->routes->add($this->createRoute($methods, $uri, $action));}/*** Create a new route instance.** @param array|string $methods* @param string $uri* @param mixed $action* @return \Illuminate\Routing\Route*/protected function createRoute($methods, $uri, $action){// If the route is routing to a controller we will parse the route action into// an acceptable array format before registering it and creating this route// instance itself. We need to build the Closure that will call this out.if ($this->actionReferencesController($action)) {$action = $this->convertToControllerAction($action);}$route = $this->newRoute($methods, $this->prefix($uri), $action);// If we have groups that need to be merged, we will merge them now after this// route has already been created and is ready to go. After we're done with// the merge we will be ready to return the route back out to the caller.if ($this->hasGroupStack()) {$this->mergeGroupAttributesIntoRoute($route);}$this->addWhereClausesToRoute($route);return $route;}/*** Determine if the action is routing to a controller.** @param mixed $action* @return bool*/protected function actionReferencesController($action){if (! $action instanceof Closure) {return is_string($action) || (isset($action['uses']) && is_string($action['uses']));}return false;}/*** Add a controller based route action to the action array.** @param array|string $action* @return array*/protected function convertToControllerAction($action){if (is_string($action)) {$action = ['uses' => $action];}// Here we'll merge any group "controller" and "uses" statements if necessary so that// the action has the proper clause for this property. Then, we can simply set the// name of this controller on the action plus return the action array for usage.if ($this->hasGroupStack()) {$action['uses'] = $this->prependGroupController($action['uses']);$action['uses'] = $this->prependGroupNamespace($action['uses']);}// Here we will set this controller name on the action array just so we always// have a copy of it for reference if we need it. This can be used while we// search for a controller name or do some other type of fetch operation.$action['controller'] = $action['uses'];return $action;}/*** Prepend the last group namespace onto the use clause.** @param string $class* @return string*/protected function prependGroupNamespace($class){$group = end($this->groupStack);return isset($group['namespace']) && ! str_starts_with($class, '\\') && ! str_starts_with($class, $group['namespace'])? $group['namespace'].'\\'.$class : $class;}/*** Prepend the last group controller onto the use clause.** @param string $class* @return string*/protected function prependGroupController($class){$group = end($this->groupStack);if (! isset($group['controller'])) {return $class;}if (class_exists($class)) {return $class;}if (str_contains($class, '@')) {return $class;}return $group['controller'].'@'.$class;}/*** Create a new Route object.** @param array|string $methods* @param string $uri* @param mixed $action* @return \Illuminate\Routing\Route*/public function newRoute($methods, $uri, $action){return (new Route($methods, $uri, $action))->setRouter($this)->setContainer($this->container);}/*** Prefix the given URI with the last prefix.** @param string $uri* @return string*/protected function prefix($uri){return trim(trim($this->getLastGroupPrefix(), '/').'/'.trim($uri, '/'), '/') ?: '/';}/*** Add the necessary where clauses to the route based on its initial registration.** @param \Illuminate\Routing\Route $route* @return \Illuminate\Routing\Route*/protected function addWhereClausesToRoute($route){$route->where(array_merge($this->patterns, $route->getAction()['where'] ?? []));return $route;}/*** Merge the group stack with the controller action.** @param \Illuminate\Routing\Route $route* @return void*/protected function mergeGroupAttributesIntoRoute($route){$route->setAction($this->mergeWithLastGroup($route->getAction(),$prependExistingPrefix = false));}/*** Return the response returned by the given route.** @param string $name* @return \Symfony\Component\HttpFoundation\Response*/public function respondWithRoute($name){$route = tap($this->routes->getByName($name))->bind($this->currentRequest);return $this->runRoute($this->currentRequest, $route);}/*** Dispatch the request to the application.** @param \Illuminate\Http\Request $request* @return \Symfony\Component\HttpFoundation\Response*/public function dispatch(Request $request){$this->currentRequest = $request;return $this->dispatchToRoute($request);}/*** Dispatch the request to a route and return the response.** @param \Illuminate\Http\Request $request* @return \Symfony\Component\HttpFoundation\Response*/public function dispatchToRoute(Request $request){return $this->runRoute($request, $this->findRoute($request));}/*** Find the route matching a given request.** @param \Illuminate\Http\Request $request* @return \Illuminate\Routing\Route*/protected function findRoute($request){$this->events->dispatch(new Routing($request));$this->current = $route = $this->routes->match($request);$route->setContainer($this->container);$this->container->instance(Route::class, $route);return $route;}/*** Return the response for the given route.** @param \Illuminate\Http\Request $request* @param \Illuminate\Routing\Route $route* @return \Symfony\Component\HttpFoundation\Response*/protected function runRoute(Request $request, Route $route){$request->setRouteResolver(fn () => $route);$this->events->dispatch(new RouteMatched($route, $request));return $this->prepareResponse($request,$this->runRouteWithinStack($route, $request));}/*** Run the given route within a Stack "onion" instance.** @param \Illuminate\Routing\Route $route* @param \Illuminate\Http\Request $request* @return mixed*/protected function runRouteWithinStack(Route $route, Request $request){$shouldSkipMiddleware = $this->container->bound('middleware.disable') &&$this->container->make('middleware.disable') === true;$middleware = $shouldSkipMiddleware ? [] : $this->gatherRouteMiddleware($route);return (new Pipeline($this->container))->send($request)->through($middleware)->then(fn ($request) => $this->prepareResponse($request, $route->run()));}/*** Gather the middleware for the given route with resolved class names.** @param \Illuminate\Routing\Route $route* @return array*/public function gatherRouteMiddleware(Route $route){return $this->resolveMiddleware($route->gatherMiddleware(), $route->excludedMiddleware());}/*** Resolve a flat array of middleware classes from the provided array.** @param array $middleware* @param array $excluded* @return array*/public function resolveMiddleware(array $middleware, array $excluded = []){$excluded = collect($excluded)->map(function ($name) {return (array) MiddlewareNameResolver::resolve($name, $this->middleware, $this->middlewareGroups);})->flatten()->values()->all();$middleware = collect($middleware)->map(function ($name) {return (array) MiddlewareNameResolver::resolve($name, $this->middleware, $this->middlewareGroups);})->flatten()->reject(function ($name) use ($excluded) {if (empty($excluded)) {return false;}if ($name instanceof Closure) {return false;}if (in_array($name, $excluded, true)) {return true;}if (! class_exists($name)) {return false;}$reflection = new ReflectionClass($name);return collect($excluded)->contains(fn ($exclude) => class_exists($exclude) && $reflection->isSubclassOf($exclude));})->values();return $this->sortMiddleware($middleware);}/*** Sort the given middleware by priority.** @param \Illuminate\Support\Collection $middlewares* @return array*/protected function sortMiddleware(Collection $middlewares){return (new SortedMiddleware($this->middlewarePriority, $middlewares))->all();}/*** Create a response instance from the given value.** @param \Symfony\Component\HttpFoundation\Request $request* @param mixed $response* @return \Symfony\Component\HttpFoundation\Response*/public function prepareResponse($request, $response){return static::toResponse($request, $response);}/*** Static version of prepareResponse.** @param \Symfony\Component\HttpFoundation\Request $request* @param mixed $response* @return \Symfony\Component\HttpFoundation\Response*/public static function toResponse($request, $response){if ($response instanceof Responsable) {$response = $response->toResponse($request);}if ($response instanceof PsrResponseInterface) {$response = (new HttpFoundationFactory)->createResponse($response);} elseif ($response instanceof Model && $response->wasRecentlyCreated) {$response = new JsonResponse($response, 201);} elseif ($response instanceof Stringable) {$response = new Response($response->__toString(), 200, ['Content-Type' => 'text/html']);} elseif (! $response instanceof SymfonyResponse &&($response instanceof Arrayable ||$response instanceof Jsonable ||$response instanceof ArrayObject ||$response instanceof JsonSerializable ||$response instanceof stdClass ||is_array($response))) {$response = new JsonResponse($response);} elseif (! $response instanceof SymfonyResponse) {$response = new Response($response, 200, ['Content-Type' => 'text/html']);}if ($response->getStatusCode() === Response::HTTP_NOT_MODIFIED) {$response->setNotModified();}return $response->prepare($request);}/*** Substitute the route bindings onto the route.** @param \Illuminate\Routing\Route $route* @return \Illuminate\Routing\Route** @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException*/public function substituteBindings($route){foreach ($route->parameters() as $key => $value) {if (isset($this->binders[$key])) {$route->setParameter($key, $this->performBinding($key, $value, $route));}}return $route;}/*** Substitute the implicit route bindings for the given route.** @param \Illuminate\Routing\Route $route* @return void** @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>* @throws \Illuminate\Routing\Exceptions\BackedEnumCaseNotFoundException*/public function substituteImplicitBindings($route){ImplicitRouteBinding::resolveForRoute($this->container, $route);}/*** Call the binding callback for the given key.** @param string $key* @param string $value* @param \Illuminate\Routing\Route $route* @return mixed** @throws \Illuminate\Database\Eloquent\ModelNotFoundException<\Illuminate\Database\Eloquent\Model>*/protected function performBinding($key, $value, $route){return call_user_func($this->binders[$key], $value, $route);}/*** Register a route matched event listener.** @param string|callable $callback* @return void*/public function matched($callback){$this->events->listen(Events\RouteMatched::class, $callback);}/*** Get all of the defined middleware short-hand names.** @return array*/public function getMiddleware(){return $this->middleware;}/*** Register a short-hand name for a middleware.** @param string $name* @param string $class* @return $this*/public function aliasMiddleware($name, $class){$this->middleware[$name] = $class;return $this;}/*** Check if a middlewareGroup with the given name exists.** @param string $name* @return bool*/public function hasMiddlewareGroup($name){return array_key_exists($name, $this->middlewareGroups);}/*** Get all of the defined middleware groups.** @return array*/public function getMiddlewareGroups(){return $this->middlewareGroups;}/*** Register a group of middleware.** @param string $name* @param array $middleware* @return $this*/public function middlewareGroup($name, array $middleware){$this->middlewareGroups[$name] = $middleware;return $this;}/*** Add a middleware to the beginning of a middleware group.** If the middleware is already in the group, it will not be added again.** @param string $group* @param string $middleware* @return $this*/public function prependMiddlewareToGroup($group, $middleware){if (isset($this->middlewareGroups[$group]) && ! in_array($middleware, $this->middlewareGroups[$group])) {array_unshift($this->middlewareGroups[$group], $middleware);}return $this;}/*** Add a middleware to the end of a middleware group.** If the middleware is already in the group, it will not be added again.** @param string $group* @param string $middleware* @return $this*/public function pushMiddlewareToGroup($group, $middleware){if (! array_key_exists($group, $this->middlewareGroups)) {$this->middlewareGroups[$group] = [];}if (! in_array($middleware, $this->middlewareGroups[$group])) {$this->middlewareGroups[$group][] = $middleware;}return $this;}/*** Remove the given middleware from the specified group.** @param string $group* @param string $middleware* @return $this*/public function removeMiddlewareFromGroup($group, $middleware){if (! $this->hasMiddlewareGroup($group)) {return $this;}$reversedMiddlewaresArray = array_flip($this->middlewareGroups[$group]);if (! array_key_exists($middleware, $reversedMiddlewaresArray)) {return $this;}$middlewareKey = $reversedMiddlewaresArray[$middleware];unset($this->middlewareGroups[$group][$middlewareKey]);return $this;}/*** Flush the router's middleware groups.** @return $this*/public function flushMiddlewareGroups(){$this->middlewareGroups = [];return $this;}/*** Add a new route parameter binder.** @param string $key* @param string|callable $binder* @return void*/public function bind($key, $binder){$this->binders[str_replace('-', '_', $key)] = RouteBinding::forCallback($this->container, $binder);}/*** Register a model binder for a wildcard.** @param string $key* @param string $class* @param \Closure|null $callback* @return void*/public function model($key, $class, Closure $callback = null){$this->bind($key, RouteBinding::forModel($this->container, $class, $callback));}/*** Get the binding callback for a given binding.** @param string $key* @return \Closure|null*/public function getBindingCallback($key){if (isset($this->binders[$key = str_replace('-', '_', $key)])) {return $this->binders[$key];}}/*** Get the global "where" patterns.** @return array*/public function getPatterns(){return $this->patterns;}/*** Set a global where pattern on all routes.** @param string $key* @param string $pattern* @return void*/public function pattern($key, $pattern){$this->patterns[$key] = $pattern;}/*** Set a group of global where patterns on all routes.** @param array $patterns* @return void*/public function patterns($patterns){foreach ($patterns as $key => $pattern) {$this->pattern($key, $pattern);}}/*** Determine if the router currently has a group stack.** @return bool*/public function hasGroupStack(){return ! empty($this->groupStack);}/*** Get the current group stack for the router.** @return array*/public function getGroupStack(){return $this->groupStack;}/*** Get a route parameter for the current route.** @param string $key* @param string|null $default* @return mixed*/public function input($key, $default = null){return $this->current()->parameter($key, $default);}/*** Get the request currently being dispatched.** @return \Illuminate\Http\Request*/public function getCurrentRequest(){return $this->currentRequest;}/*** Get the currently dispatched route instance.** @return \Illuminate\Routing\Route|null*/public function getCurrentRoute(){return $this->current();}/*** Get the currently dispatched route instance.** @return \Illuminate\Routing\Route|null*/public function current(){return $this->current;}/*** Check if a route with the given name exists.** @param string|array $name* @return bool*/public function has($name){$names = is_array($name) ? $name : func_get_args();foreach ($names as $value) {if (! $this->routes->hasNamedRoute($value)) {return false;}}return true;}/*** Get the current route name.** @return string|null*/public function currentRouteName(){return $this->current() ? $this->current()->getName() : null;}/*** Alias for the "currentRouteNamed" method.** @param mixed ...$patterns* @return bool*/public function is(...$patterns){return $this->currentRouteNamed(...$patterns);}/*** Determine if the current route matches a pattern.** @param mixed ...$patterns* @return bool*/public function currentRouteNamed(...$patterns){return $this->current() && $this->current()->named(...$patterns);}/*** Get the current route action.** @return string|null*/public function currentRouteAction(){if ($this->current()) {return $this->current()->getAction()['controller'] ?? null;}}/*** Alias for the "currentRouteUses" method.** @param array ...$patterns* @return bool*/public function uses(...$patterns){foreach ($patterns as $pattern) {if (Str::is($pattern, $this->currentRouteAction())) {return true;}}return false;}/*** Determine if the current route action matches a given action.** @param string $action* @return bool*/public function currentRouteUses($action){return $this->currentRouteAction() == $action;}/*** Set the unmapped global resource parameters to singular.** @param bool $singular* @return void*/public function singularResourceParameters($singular = true){ResourceRegistrar::singularParameters($singular);}/*** Set the global resource parameter mapping.** @param array $parameters* @return void*/public function resourceParameters(array $parameters = []){ResourceRegistrar::setParameters($parameters);}/*** Get or set the verbs used in the resource URIs.** @param array $verbs* @return array|null*/public function resourceVerbs(array $verbs = []){return ResourceRegistrar::verbs($verbs);}/*** Get the underlying route collection.** @return \Illuminate\Routing\RouteCollectionInterface*/public function getRoutes(){return $this->routes;}/*** Set the route collection instance.** @param \Illuminate\Routing\RouteCollection $routes* @return void*/public function setRoutes(RouteCollection $routes){foreach ($routes as $route) {$route->setRouter($this)->setContainer($this->container);}$this->routes = $routes;$this->container->instance('routes', $this->routes);}/*** Set the compiled route collection instance.** @param array $routes* @return void*/public function setCompiledRoutes(array $routes){$this->routes = (new CompiledRouteCollection($routes['compiled'], $routes['attributes']))->setRouter($this)->setContainer($this->container);$this->container->instance('routes', $this->routes);}/*** Remove any duplicate middleware from the given array.** @param array $middleware* @return array*/public static function uniqueMiddleware(array $middleware){$seen = [];$result = [];foreach ($middleware as $value) {$key = \is_object($value) ? \spl_object_id($value) : $value;if (! isset($seen[$key])) {$seen[$key] = true;$result[] = $value;}}return $result;}/*** Set the container instance used by the router.** @param \Illuminate\Container\Container $container* @return $this*/public function setContainer(Container $container){$this->container = $container;return $this;}/*** Dynamically handle calls into the router instance.** @param string $method* @param array $parameters* @return mixed*/public function __call($method, $parameters){if (static::hasMacro($method)) {return $this->macroCall($method, $parameters);}if ($method === 'middleware') {return (new RouteRegistrar($this))->attribute($method, is_array($parameters[0]) ? $parameters[0] : $parameters);}if ($method !== 'where' && Str::startsWith($method, 'where')) {return (new RouteRegistrar($this))->{$method}(...$parameters);}return (new RouteRegistrar($this))->attribute($method, array_key_exists(0, $parameters) ? $parameters[0] : true);}}