Вход Регистрация
Файл: vendor/laravel/framework/src/Illuminate/Routing/Router.php
Строк: 1672
<?php

namespace IlluminateRouting;

use 
ArrayObject;
use 
Closure;
use 
IlluminateContainerContainer;
use 
IlluminateContractsEventsDispatcher;
use 
IlluminateContractsRoutingBindingRegistrar;
use 
IlluminateContractsRoutingRegistrar as RegistrarContract;
use 
IlluminateContractsSupportArrayable;
use 
IlluminateContractsSupportJsonable;
use 
IlluminateContractsSupportResponsable;
use 
IlluminateDatabaseEloquentModel;
use 
IlluminateHttpJsonResponse;
use 
IlluminateHttpRequest;
use 
IlluminateHttpResponse;
use 
IlluminateRoutingEventsPreparingResponse;
use 
IlluminateRoutingEventsResponsePrepared;
use 
IlluminateRoutingEventsRouteMatched;
use 
IlluminateRoutingEventsRouting;
use 
IlluminateSupportArr;
use 
IlluminateSupportCollection;
use 
IlluminateSupportStr;
use 
IlluminateSupportStringable;
use 
IlluminateSupportTraitsMacroable;
use 
JsonSerializable;
use 
PsrHttpMessageResponseInterface as PsrResponseInterface;
use 
ReflectionClass;
use 
stdClass;
use 
SymfonyBridgePsrHttpMessageFactoryHttpFoundationFactory;
use 
SymfonyComponentHttpFoundationResponse as SymfonyResponse;

/**
 * @mixin IlluminateRoutingRouteRegistrar
 */
class Router implements BindingRegistrarRegistrarContract
{
    use 
Macroable {
        
__call as macroCall;
    }

    
/**
     * The event dispatcher instance.
     *
     * @var IlluminateContractsEventsDispatcher
     */
    
protected $events;

    
/**
     * The IoC container instance.
     *
     * @var IlluminateContainerContainer
     */
    
protected $container;

    
/**
     * The route collection instance.
     *
     * @var IlluminateRoutingRouteCollectionInterface
     */
    
protected $routes;

    
/**
     * The currently dispatched route instance.
     *
     * @var IlluminateRoutingRoute|null
     */
    
protected $current;

    
/**
     * The request currently being dispatched.
     *
     * @var IlluminateHttpRequest
     */
    
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 = [];

    
/**
     * The registered custom implicit binding callback.
     *
     * @var array
     */
    
protected $implicitBindingCallback;

    
/**
     * 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  IlluminateContractsEventsDispatcher  $events
     * @param  IlluminateContainerContainer|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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
public function redirect($uri$destination$status 302)
    {
        return 
$this->any($uri'IlluminateRoutingRedirectController')
                ->
defaults('destination'$destination)
                ->
defaults('status'$status);
    }

    
/**
     * Create a permanent redirect from one URI to another.
     *
     * @param  string  $uri
     * @param  string  $destination
     * @return IlluminateRoutingRoute
     */
    
public function permanentRedirect($uri$destination)
    {
        return 
$this->redirect($uri$destination301);
    }

    
/**
     * 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 IlluminateRoutingRoute
     */
    
public function view($uri$view$data = [], $status 200, array $headers = [])
    {
        return 
$this->match(['GET''HEAD'], $uri'IlluminateRoutingViewController')
                ->
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingPendingResourceRegistration
     */
    
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 IlluminateRoutingPendingResourceRegistration
     */
    
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$controllerarray_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 IlluminateRoutingPendingSingletonResourceRegistration
     */
    
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 IlluminateRoutingPendingSingletonResourceRegistration
     */
    
public function apiSingleton($name$controller, array $options = [])
    {
        
$only = ['store''show''update''destroy'];

        if (isset(
$options['except'])) {
            
$only array_diff($only, (array) $options['except']);
        }

        return 
$this->singleton($name$controllerarray_merge([
            
'only' => $only,
        ], 
$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($newend($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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    
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 IlluminateRoutingRoute
     */
    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  IlluminateRoutingRoute  $route
     * @return IlluminateRoutingRoute
     */
    protected function addWhereClausesToRoute($route)
    {
        $route->where(array_merge(
            $this->patterns, $route->getAction()['
where'] ?? []
        ));

        return $route;
    }

    /**
     * Merge the group stack with the controller action.
     *
     * @param  IlluminateRoutingRoute  $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 SymfonyComponentHttpFoundationResponse
     */
    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  IlluminateHttpRequest  $request
     * @return SymfonyComponentHttpFoundationResponse
     */
    public function dispatch(Request $request)
    {
        $this->currentRequest = $request;

        return $this->dispatchToRoute($request);
    }

    /**
     * Dispatch the request to a route and return the response.
     *
     * @param  IlluminateHttpRequest  $request
     * @return SymfonyComponentHttpFoundationResponse
     */
    public function dispatchToRoute(Request $request)
    {
        return $this->runRoute($request, $this->findRoute($request));
    }

    /**
     * Find the route matching a given request.
     *
     * @param  IlluminateHttpRequest  $request
     * @return IlluminateRoutingRoute
     */
    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  IlluminateHttpRequest  $request
     * @param  IlluminateRoutingRoute  $route
     * @return SymfonyComponentHttpFoundationResponse
     */
    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  IlluminateRoutingRoute  $route
     * @param  IlluminateHttpRequest  $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  IlluminateRoutingRoute  $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  IlluminateSupportCollection  $middlewares
     * @return array
     */
    protected function sortMiddleware(Collection $middlewares)
    {
        return (new SortedMiddleware($this->middlewarePriority, $middlewares))->all();
    }

    /**
     * Create a response instance from the given value.
     *
     * @param  SymfonyComponentHttpFoundationRequest  $request
     * @param  mixed  $response
     * @return SymfonyComponentHttpFoundationResponse
     */
    public function prepareResponse($request, $response)
    {
        $this->events->dispatch(new PreparingResponse($request, $response));

        return tap(static::toResponse($request, $response), function ($response) use ($request) {
            $this->events->dispatch(new ResponsePrepared($request, $response));
        });
    }

    /**
     * Static version of prepareResponse.
     *
     * @param  SymfonyComponentHttpFoundationRequest  $request
     * @param  mixed  $response
     * @return SymfonyComponentHttpFoundationResponse
     */
    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  IlluminateRoutingRoute  $route
     * @return IlluminateRoutingRoute
     *
     * @throws IlluminateDatabaseEloquentModelNotFoundException<IlluminateDatabaseEloquentModel>
     * @throws IlluminateRoutingExceptionsBackedEnumCaseNotFoundException
     */
    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  IlluminateRoutingRoute  $route
     * @return void
     *
     * @throws IlluminateDatabaseEloquentModelNotFoundException<IlluminateDatabaseEloquentModel>
     * @throws IlluminateRoutingExceptionsBackedEnumCaseNotFoundException
     */
    public function substituteImplicitBindings($route)
    {
        $default = fn () => ImplicitRouteBinding::resolveForRoute($this->container, $route);

        return call_user_func(
            $this->implicitBindingCallback ?? $default, $this->container, $route, $default
        );
    }

    /**
     * Register a callback to to run after implicit bindings are substituted.
     *
     * @param  callable  $callback
     * @return $this
     */
    public function substituteImplicitBindingsUsing($callback)
    {
        $this->implicitBindingCallback = $callback;

        return $this;
    }

    /**
     * Call the binding callback for the given key.
     *
     * @param  string  $key
     * @param  string  $value
     * @param  IlluminateRoutingRoute  $route
     * @return mixed
     *
     * @throws IlluminateDatabaseEloquentModelNotFoundException<IlluminateDatabaseEloquentModel>
     */
    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(EventsRouteMatched::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($keyRouteBinding::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 IlluminateHttpRequest
     */
    
public function getCurrentRequest()
    {
        return 
$this->currentRequest;
    }

    
/**
     * Get the currently dispatched route instance.
     *
     * @return IlluminateRoutingRoute|null
     */
    
public function getCurrentRoute()
    {
        return 
$this->current();
    }

    
/**
     * Get the currently dispatched route instance.
     *
     * @return IlluminateRoutingRoute|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 IlluminateRoutingRouteCollectionInterface
     */
    
public function getRoutes()
    {
        return 
$this->routes;
    }

    
/**
     * Set the route collection instance.
     *
     * @param  IlluminateRoutingRouteCollection  $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  IlluminateContainerContainer  $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($methodis_array($parameters[0]) ? $parameters[0] : $parameters);
        }

        if (
$method !== 'where' && Str::startsWith($method'where')) {
            return (new 
RouteRegistrar($this))->{$method}(...$parameters);
        }

        return (new 
RouteRegistrar($this))->attribute($methodarray_key_exists(0$parameters) ? $parameters[0] : true);
    }
}
Онлайн: 0
Реклама