Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Routing Laravel

Routing Laravel

Let's find how Route:: works and where we can reuse it for our own technical challenges.

Talk was given at Laracon Online 2021, march 17th.

27023728a22ac6d6a38342c1c1b2cb6e?s=128

Bobby Bouwmann

March 17, 2021
Tweet

Transcript

  1. Routing Laravel Photo by Franco Antonio Giovanella on Unsplash

  2. None
  3. Laravel Fashionista • Laravel Evangelist @ Enrise • Top Contributor

    @ Laracasts • Writer of Laravel Secrets • Partner @ PingPing.io @bobbybouwmann
  4. Enrise We are the new standard in organising No management,

    no board, but professionals who take control
  5. Better order that pizza now! • Laravel basic routing •

    Routing cycle • Route model binding explained • Another use case for the router • Best practices Today’s menu Photo by Natasha Filippovskaya from Pexels
  6. <?ph p use Illuminate\Support\Facades\Route ; / * |------------------------------------------------------------------------- - |

    Web Route s |------------------------------------------------------------------------- - | | Here is where you can register web routes for your application. Thes e | routes are loaded by the RouteServiceProvider within a group whic h | contains the "web" middleware group. Now create something great ! | * / Route::get('/', function () { return view('welcome') ; });
  7. // Basic Controller Route::get('/users/{user}', [UsersController::class, ‘show'] ) ->name('users.show') ; //

    Invokable Controlle r Route::get('/users/{user}', EditUser::class ) ->name(‘users.edit') ; // Callbac k Route::get('/', function () { return view('welcome') ; });
  8. Route::get('posts', [PostsController::class, ‘index'])->name('posts.index') ; Route::get('posts/create', [PostsController::class, ‘create'])->name('posts.create') ; Route::post('posts', [PostsController::class,

    ‘store'])->name('posts.store') ; Route::get('posts/{post}', [PostsController::class, ‘show'])->name('posts.show') ; Route::get('posts/{post}/edit', [PostsController::class, ‘edit'])->name('posts.edit') ; Route::put('posts/{post}', [PostsController::class, ‘update’])->name('posts.update') ; Route::patch('posts/{post}', [PostsController::class, ‘update'])->name('posts.update') ; Route::delete('posts/{post}', [PostsController::class, ‘destroy'])->name('posts.destroy');
  9. $ php artisan route:list +-----------+--------------------+----------------+-----------------------------------------------+------------+ | Method | URI |

    Name | Action | Middleware | +-----------+--------------------+----------------+-----------------------------------------------+------------+ | GET|HEAD | posts | posts.index | App\Http\Controllers\PostsController@index | web | | POST | posts | posts.store | App\Http\Controllers\PostsController@store | web | | GET|HEAD | posts/create | posts.create | App\Http\Controllers\PostsController@create | web | | GET|HEAD | posts/{post} | posts.show | App\Http\Controllers\PostsController@show | web | | PUT|PATCH | posts/{post} | posts.update | App\Http\Controllers\PostsController@update | web | | DELETE | posts/{post} | posts.destroy | App\Http\Controllers\PostsController@destroy | web | | GET|HEAD | posts/{post}/edit | posts.edit | App\Http\Controllers\PostsController@edit | web | +-----------+--------------------+----------------+-----------------------------------------------+------------+ $ php artisan route:list --compact +-----------+--------------------+-----------------------------------------------+ | Method | URI | Action | +-----------+--------------------+-----------------------------------------------+ | GET|HEAD | posts | App\Http\Controllers\PostsController@index | | POST | posts | App\Http\Controllers\PostsController@store | | GET|HEAD | posts/create | App\Http\Controllers\PostsController@create | | GET|HEAD | posts/{post} | App\Http\Controllers\PostsController@show | | PUT|PATCH | posts/{post} | App\Http\Controllers\PostsController@update | | DELETE | posts/{post} | App\Http\Controllers\PostsController@destroy | | GET|HEAD | posts/{post}/edit | App\Http\Controllers\PostsController@edit | +-----------+--------------------+-----------------------------------------------+
  10. Route::resource('posts', PostsController::class); $ php artisan route:list --compact +-----------+--------------------+-----------------------------------------------+ | Method

    | URI | Action | +-----------+--------------------+-----------------------------------------------+ | GET|HEAD | / | Closure | | GET|HEAD | posts | App\Http\Controllers\PostsController@index | | POST | posts | App\Http\Controllers\PostsController@store | | GET|HEAD | posts/create | App\Http\Controllers\PostsController@create | | GET|HEAD | posts/{post} | App\Http\Controllers\PostsController@show | | PUT|PATCH | posts/{post} | App\Http\Controllers\PostsController@update | | DELETE | posts/{post} | App\Http\Controllers\PostsController@destroy | | GET|HEAD | posts/{post}/edit | App\Http\Controllers\PostsController@edit | +-----------+--------------------+-----------------------------------------------+
  11. Route::resource('posts', PostsController::class) ; Route::resource('posts', PostsController::class)->except(['index']) ; Route::resource('posts', PostsController::class)->only(['index', 'create', 'show'])

    ; Route::get('posts/{post}/publish', [PostsController::class, ‘publish'] ) ->name(‘posts.publish') ;
  12. Route::resource('posts', PostsController::class)->middleware(‘auth')->names('blog'); Route::resource('posts', PostsController::class)->name('index', 'blog'); $ php artisan route:list +-----------+--------------------+----------------+-----------------------------------------------+------------+

    | Method | URI | Name | Action | Middleware | +-----------+--------------------+----------------+-----------------------------------------------+------------+ | GET|HEAD | posts | blog.index | App\Http\Controllers\PostsController@index | web, auth | | POST | posts | blog.store | App\Http\Controllers\PostsController@store | web, auth | | GET|HEAD | posts/create | blog.create | App\Http\Controllers\PostsController@create | web, auth | | GET|HEAD | posts/{post} | blog.show | App\Http\Controllers\PostsController@show | web, auth | | PUT|PATCH | posts/{post} | blog.update | App\Http\Controllers\PostsController@update | web, auth | +-----------+--------------------+----------------+-----------------------------------------------+------------+ $ php artisan route:list +-----------+--------------------+----------------+-----------------------------------------------+------------+ | Method | URI | Name | Action | Middleware | +-----------+--------------------+----------------+-----------------------------------------------+------------+ | GET|HEAD | posts | blog | App\Http\Controllers\PostsController@index | web | | POST | posts | posts.store | App\Http\Controllers\PostsController@store | web | | GET|HEAD | posts/create | posts.create | App\Http\Controllers\PostsController@create | web | | GET|HEAD | posts/{post} | posts.show | App\Http\Controllers\PostsController@show | web | | PUT|PATCH | posts/{post} | posts.update | App\Http\Controllers\PostsController@update | web | +-----------+--------------------+----------------+-----------------------------------------------+------------+
  13. Route::name('posts.index' ) ->prefix('posts' ) ->middleware('auth' ) ->domain('portal.example.com' ) ->get('list', [PostsController::class,

    'index']) ; Route::name('posts.update' ) ->prefix('posts' ) ->middleware('auth' ) ->domain('portal.example.com' ) ->patch('{post}', [PostsController::class, 'update']); $ php artisan route:list +--------------------+----------+-------------+--------------+---------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------------------+----------+-------------+--------------+---------------------------------------------+------------+ | portal.example.com | GET|HEAD | posts/list | posts.index | App\Http\Controllers\PostsController@index | web | | | | | | | auth | | portal.example.com | PATCH | posts/{post}| posts.update | App\Http\Controllers\PostsController@update | web | | | | | | | auth | +--------------------+----------+-------------+--------------+---------------------------------------------+------------+
  14. Route::name('posts.' ) ->prefix('posts' ) ->middleware('auth' ) ->domain('{vendor}.example.com' ) ->group(function ()

    { Route::get('list', [PostsController::class, 'index'])->name('list') ; Route::get('public', [PostsController::class, 'public'])->name('public') ; }) ; $ php artisan route:list +----------------------+----------+--------------------+-----------------+------------------------------------------------+------------+ | Domain | Method | URI | Name | Action | Middleware | +----------------------+----------+--------------------+-----------------+------------------------------------------------+------------+ | {vendor}.example.com | GET|HEAD | posts/list | posts.list | App\Http\Controllers\PostsController@index | web | | | | | | | auth | | {vendor}.example.com | GET|HEAD | posts/published | posts.published | App\Http\Controllers\PostsController@published | web | | | | | | | auth | +----------------------+----------+--------------------+-----------------+------------------------------------------------+------------+
  15. Route::middleware('auth')->group(function () { Route::get('blog/{post}', [PostsController::class, 'show'])->name('posts.show') ; Route::middleware('throttle:10|60,1')->group(function () {

    Route::get('blog', [PostsController::class, 'index'])->name('posts.index') ; }) ; Route::middleware('verified')->group(function () { Route::get('posts/create', [PostsController::class, 'create'])->name('posts.index') ; Route::post('posts/store', [PostsController::class, 'store'])->name('posts.store') ; }) ; }); $ php artisan route:list --columns=method,name,action,middleware +----------+-------------+---------------------------------------------+------------------+ | Method | Name | Action | Middleware | +----------+-------------+---------------------------------------------+------------------+ | GET|HEAD | posts.index | App\Http\Controllers\PostsController@index | web | | | | | auth | | | | | throttle:10|60,1 | | GET|HEAD | posts.show | App\Http\Controllers\PostsController@show | web | | | | | auth | | GET|HEAD | posts.index | App\Http\Controllers\PostsController@create | web | | | | | auth | | | | | verified | | POST | posts.store | App\Http\Controllers\PostsController@store | web | | | | | auth | | | | | verified | +----------+-------------+---------------------------------------------+------------------+
  16. <?ph p namespace App\Providers ; use Illuminate\Cache\RateLimiting\Limit ; use Illuminate\Foundation\Support\Providers\RouteServiceProvider

    as ServiceProvider ; use Illuminate\Http\Request ; use Illuminate\Support\Facades\RateLimiter ; use Illuminate\Support\Facades\Route ; class RouteServiceProvider extends ServiceProvide r { /* * * The path to the "home" route for your application . * * This is used by Laravel authentication to redirect users after login . * * @var strin g * / public const HOME = '/home' ; /* * * The controller namespace for the application . * * When present, controller route declarations will automatically be prefixed with this namespace . * * @var string|nul l * / // protected $namespace = 'App\\Http\\Controllers' ;
  17. ; use Illuminate\Support\Facades\Route ; class RouteServiceProvider extends ServiceProvide r {

    /* * * The path to the "home" route for your application . * * This is used by Laravel authentication to redirect users after login . * * @var strin g * / public const HOME = '/home' ; /* * * The controller namespace for the application . * * When present, controller route declarations will automatically be prefixed with this namespace . * * @var string|nul l * / // protected $namespace = 'App\\Http\\Controllers' ; /* * * Define your route model bindings, pattern filters, etc . * * @return voi d * / public function boot( ) { $this->configureRateLimiting() ; protected $namespace = 'App\\Http\\Controllers'; Route::get('/users/{user}', 'UsersController@show');
  18. /* * * Define your route model bindings, pattern filters,

    etc . * * @return voi d * / public function boot( ) { $this->configureRateLimiting() ; $this->routes(function () { Route::prefix('api' ) ->middleware('api' ) ->namespace($this->namespace ) ->group(base_path('routes/api.php')) ; Route::middleware('web' ) ->namespace($this->namespace ) ->group(base_path('routes/web.php')) ; }) ; } /* * * Configure the rate limiters for the application . * * @return voi d * / protected function configureRateLimiting( ) { RateLimiter::for('api', function (Request $request) { return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()) ; ;
  19. Route::match(['get', 'post'], 'login', function (Request $request) { / / })->name('login')

    ; Route::any('register', function (Request $request) { / / })->name('register'); $ php artisan route:list --columns=method,name,action,middleware +----------------------------------------+----------------+----------------+------------+ | Method | Name | Action | Middleware | +----------------------------------------+----------------+----------------+------------+ | GET|POST|HEAD | login | Closure | web | | GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS | register | Closure | web | +----------------------------------------+----------------+----------------+------------+
  20. Route::get('dashboard', DashboardController::class)->name('dashboard') ; // Redirect to a different URL, HTTP

    status code 30 2 Route::redirect('/app', '/dashboard') ; // Permanent redirect to a different URL, , HTTP status code 30 1 Route::permanentRedirect('contact', '/#contact'); $ php artisan route:list --columns=method,uri,name,action +----------------------------------------+------------+------------+------------------------------------------+ | Method | URI | Name | Action | +----------------------------------------+------------+------------+------------------------------------------+ | GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS | app | | Illuminate\Routing\RedirectController | | GET|HEAD|POST|PUT|PATCH|DELETE|OPTIONS | contact | | Illuminate\Routing\RedirectController | | GET|HEAD | dashboard | dashboard | App\Http\Controllers\DashboardController | +----------------------------------------+------------+------------+------------------------------------------+
  21. Route::view('/home', 'welcome')->name('welcome') ; // With additional dat a Route::view('/home', 'welcome',

    ['title' => 'Welcome'])->name('welcome'); $ php artisan route:list --columns=method,uri,name,action +----------------------------------------+------------+------------+------------------------------------------+ | Method | URI | Name | Action | +----------------------------------------+------------+------------+------------------------------------------+ | GET|HEAD | home | welcome | Illuminate\Routing\ViewController | +----------------------------------------+------------+------------+------------------------------------------+
  22. Route::fallback(function () { return redirect()->route('welcome') ; }) ; Route::fallback('App\Http\Controllers\AirportsController@index'); $

    php artisan route:list --columns=method,uri,name,action +----------------+-----------------------+--------+-------------------------------------------------+ | Method | URI | Name | Action | +----------------+-----------------------+--------+-------------------------------------------------+ | GET|HEAD | {fallbackPlaceholder} | | App\Http\Controllers\AirportsController@index | +----------------+-----------------------+--------+-------------------------------------------------+
  23. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ;

  24. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // https://example.com/customers/ 1 $url =

    route('customers.show', 1) ;
  25. // Befor e Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // Afte

    r Route::get(‘customers/{customer}/details’, ShowCustomerController::class ) ->name(‘customers.show’); // Before: https://example.com/customers/ 1 $url = route('customers.show', 1) ; // After: https://example.com/customers/1/detail s $url = route('customers.show', 1) ;
  26. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // https://example.com/customers/ 1 $url =

    route('customers.show', 1) ; // https://example.com/customers/ 1 $url = route('customers.show', Customer::find(1)) ;
  27. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // https://example.com/customers/ 1 $url =

    route('customers.show', 1) ; // https://example.com/customers/ 1 $url = route('customers.show', $customer) ; // https://example.com/customers/1?withInvoice= 1 $url = route('customers.show', ['customer' => $customer, 'withInvoice' => true]) ;
  28. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // https://example.com/customers/ 1 $url =

    route('customers.show', 1) ; // https://example.com/customers/ 1 $url = route('customers.show', $customer) ; // https://example.com/customers/1?withInvoice= 1 $url = route('customers.show', ['customer' => $customer, 'withInvoice' => true]) ; // https://example.com/customers/1?signatur e $url = route('customers.show', [$customer, 'signature']) ;
  29. Route::get('customers/{customer}', ShowCustomerController::class ) ->name(‘customers.show’) ; // https://example.com/customers/ 1 $url =

    route('customers.show', 1) ; // https://example.com/customers/ 1 $url = route('customers.show', $customer) ; // https://example.com/customers/1?withInvoice= 1 $url = route('customers.show', ['customer' => $customer, 'withInvoice' => true]) ; // https://example.com/customers/1?signatur e $url = route('customers.show', [$customer, 'signature']) ;
  30. public function update(CustomerRequest $request, Customer $customer ) { $customer->update($request->only(['company'])) ;

    return redirect()->route('customers.show', $customer) ; }
  31. public function handle(Request $request, Closure $next ) { if (!

    Auth::check() && $request->route()->named('customers.show')) { return redirect()->route('dashboard') ; } return $next($request) ; }
  32. Route::get('/users/{user}', [UsersController::class, ‘show'])->name('users.show') ; // Illuminate\Routing\Rout e $current = Route::current()

    ; // users.nam e $name = Route::currentRouteName() ; // App\Http\Controllers\UsersController@sho w $action = Route::currentRouteAction() ;
  33. Did you order your pizza already? Routing cycle Photo by

    Anete Lusina from Pexels
  34. // public/index.ph p / * |------------------------------------------------------------------------- - | Run The

    Applicatio n |------------------------------------------------------------------------- - | | Once we have the application, we can handle the incoming request usin g | the application's HTTP kernel. Then, we will send the response bac k | to this client's browser, allowing them to enjoy our application . | * / $app = require_once __DIR__.'/../bootstrap/app.php' ; $kernel = $app->make(Kernel::class) ; $response = tap($kernel->handle ( $request = Request::capture( ) ))->send() ; $kernel->terminate($request, $response) ;
  35. // app/Http/Kernel.ph p namespace App\Http ; use Illuminate\Foundation\Http\Kernel as HttpKernel

    ; class Kernel extends HttpKerne l { /* * * The application's global HTTP middleware stack . * These middleware are run during every request to your application . * / protected $middleware = [ ] ; /* * * The application's route middleware groups . * / protected $middlewareGroups = [ ] ; /* * * The application's route middleware . * These middleware may be assigned to groups or used individually . * / protected $routeMiddleware = [ ] ; }
  36. // app/Http/Kernel.ph p namespace App\Http ; use Illuminate\Foundation\Http\Kernel as HttpKernel

    ; class Kernel extends HttpKerne l { /* * * The application's global HTTP middleware stack . * * These middleware are run during every request to your application . * * @var arra y * / protected $middleware = [ // \App\Http\Middleware\TrustHosts::class , \App\Http\Middleware\TrustProxies::class , \Fruitcake\Cors\HandleCors::class , \App\Http\Middleware\PreventRequestsDuringMaintenance::class , \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class , \App\Http\Middleware\TrimStrings::class , \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class , ] ; }
  37. // app/Http/Kernel.ph p namespace App\Http ; use Illuminate\Foundation\Http\Kernel as HttpKernel

    ; class Kernel extends HttpKerne l { /* * * The application's route middleware groups . * / protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class , \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class , \Illuminate\Session\Middleware\StartSession::class , // \Illuminate\Session\Middleware\AuthenticateSession::class , \Illuminate\View\Middleware\ShareErrorsFromSession::class , \App\Http\Middleware\VerifyCsrfToken::class , \Illuminate\Routing\Middleware\SubstituteBindings::class , ] , 'api' => [ 'throttle:api' , \Illuminate\Routing\Middleware\SubstituteBindings::class , ] , ] ; }
  38. // app/Http/Kernel.ph p namespace App\Http ; use Illuminate\Foundation\Http\Kernel as HttpKernel

    ; class Kernel extends HttpKerne l { /* * * The application's route middleware . * * These middleware may be assigned to groups or used individually . * * @var arra y * / protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class , 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class , 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class , 'can' => \Illuminate\Auth\Middleware\Authorize::class , 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class , 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class , 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class , 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class , 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class , ] ; }
  39. // app/Http/Kernel.ph p namespace App\Http ; use Illuminate\Foundation\Http\Kernel as HttpKernel

    ; class Kernel extends HttpKerne l { /* * * The application's global HTTP middleware stack . * These middleware are run during every request to your application . * / protected $middleware = [ ] ; /* * * The application's route middleware groups . * / protected $middlewareGroups = [ ] ; /* * * The application's route middleware . * These middleware may be assigned to groups or used individually . * / protected $routeMiddleware = [ ] ; }
  40. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { public function handle($request ) { try { $request->enableHttpMethodParameterOverride() ; $response = $this->sendRequestThroughRouter($request) ; } catch (Throwable $e) { $this->reportException($e) ; $response = $this->renderException($request, $e) ; } $this->app['events']->dispatch ( new RequestHandled($request, $response ) ) ; return $response ; } }
  41. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { /* * * Send the given request through the middleware / router . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Http\Respons e * / protected function sendRequestThroughRouter($request ) { $this->app->instance('request', $request) ; Facade::clearResolvedInstance('request') ; $this->bootstrap() ; return (new Pipeline($this->app) ) ->send($request ) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware ) ->then($this->dispatchToRouter()) ; } }
  42. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { /* * * Send the given request through the middleware / router . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Http\Respons e * / protected function sendRequestThroughRouter($request ) { $this->app->instance('request', $request) ; Facade::clearResolvedInstance('request') ; $this->bootstrap() ; return (new Pipeline($this->app) ) ->send($request ) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware ) ->then($this->dispatchToRouter()) ; } }
  43. // app/Providers/RouteServiceProvider.ph p namespace App\Providers ; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider

    ; class RouteServiceProvider extends ServiceProvide r { /* * * Define your route model bindings, pattern filters, etc . * * @return voi d * / public function boot( ) { $this->configureRateLimiting() ; $this->routes(function () { Route::prefix('api' ) ->middleware('api' ) ->namespace($this->namespace ) ->group(base_path('routes/api.php')) ; Route::middleware('web' ) ->namespace($this->namespace ) ->group(base_path('routes/web.php')) ; }) ; } }
  44. // vendor/laravel/framework/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.ph p namespace Illuminate\Foundation\Support\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Register the callback that will be used to load the application's routes . * * @param \Closure $routesCallbac k * @return $thi s * / protected function routes(Closure $routesCallback ) { $this->loadRoutesUsing = $routesCallback ; return $this ; } }
  45. // vendor/laravel/framework/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.ph p namespace Illuminate\Foundation\Support\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Register any application services . * * @return voi d * / public function register( ) { $this->booted(function () { $this->setRootControllerNamespace() ; if ($this->routesAreCached()) { $this->loadCachedRoutes() ; } else { $this->loadRoutes() ; $this->app->booted(function () { $this->app['router']->getRoutes()->refreshNameLookups() ; $this->app['router']->getRoutes()->refreshActionLookups() ; }) ; } }) ; } }
  46. // vendor/laravel/framework/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.ph p namespace Illuminate\Foundation\Support\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Load the application routes . * * @return voi d * / protected function loadRoutes( ) { if (! is_null($this->loadRoutesUsing)) { $this->app->call($this->loadRoutesUsing) ; } elseif (method_exists($this, 'map')) { $this->app->call([$this, 'map']) ; } } }
  47. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContract { /* * * Register a new GET route with the router . * * @return \Illuminate\Routing\Rout e * / public function get($uri, $action = null ) { return $this->addRoute(['GET', 'HEAD'], $uri, $action) ; } /* * * Register a new POST route with the router . * * @return \Illuminate\Routing\Rout e * / public function post($uri, $action = null ) { return $this->addRoute('POST', $uri, $action) ; } }
  48. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContract { /* * * Add a route to the underlying route collection . * * @param array|string $method s * @param string $ur i * @param array|string|callable|null $actio n * @return \Illuminate\Routing\Rout e * / public function addRoute($methods, $uri, $action ) { return $this->routes->add($this->createRoute($methods, $uri, $action)) ; } }
  49. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContract { protected function createRoute($methods, $uri, $action ) { // If the route is routing to a controller we will parse the route action int o // an acceptable array format before registering i t if ($this->actionReferencesController($action)) { $action = $this->convertToControllerAction($action) ; } $route = $this->newRoute ( $methods, $this->prefix($uri), $actio n ) ; // If we have groups that need to be merged, we will merge them now after thi s // route has already been created and is ready to go . if ($this->hasGroupStack()) { $this->mergeGroupAttributesIntoRoute($route) ; } $this->addWhereClausesToRoute($route) ; return $route ; } }
  50. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContract { /* * * Add a route to the underlying route collection . * * @param array|string $method s * @param string $ur i * @param array|string|callable|null $actio n * @return \Illuminate\Routing\Rout e * / public function addRoute($methods, $uri, $action ) { return $this->routes->add($this->createRoute($methods, $uri, $action)) ; } }
  51. // vendor/laravel/framework/src/Illuminate/Foundation/Support/Providers/RouteServiceProvider.ph p namespace Illuminate\Foundation\Support\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Register any application services . * * @return voi d * / public function register( ) { $this->booted(function () { $this->setRootControllerNamespace() ; if ($this->routesAreCached()) { $this->loadCachedRoutes() ; } else { $this->loadRoutes() ; $this->app->booted(function () { $this->app['router']->getRoutes()->refreshNameLookups() ; $this->app['router']->getRoutes()->refreshActionLookups() ; }) ; } }) ; } }
  52. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { /* * * Send the given request through the middleware / router . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Http\Respons e * / protected function sendRequestThroughRouter($request ) { $this->app->instance('request', $request) ; Facade::clearResolvedInstance('request') ; $this->bootstrap() ; return (new Pipeline($this->app) ) ->send($request ) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware ) ->then($this->dispatchToRouter()) ; } }
  53. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { /* * * The router instance . * * @var \Illuminate\Routing\Route r * / protected $router ; /* * * Get the route dispatcher callback . * * @return \Closur e * / protected function dispatchToRouter( ) { return function ($request) { $this->app->instance('request', $request) ; return $this->router->dispatch($request) ; } ; } }
  54. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Dispatch the request to the application . * * @param \Illuminate\Http\Request $reques t * @return \Symfony\Component\HttpFoundation\Respons e * / public function dispatch(Request $request ) { $this->currentRequest = $request ; return $this->dispatchToRoute($request) ; } /* * * Dispatch the request to a route and return the response . * / public function dispatchToRoute(Request $request ) { return $this->runRoute($request, $this->findRoute($request)) ; } }
  55. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * The route collection instance . * * @var \Illuminate\Routing\RouteCollectionInterfac e * / protected $routes ; /* * * Find the route matching a given request . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Routing\Rout e * / protected function findRoute($request ) { $this->current = $route = $this->routes->match($request) ; $this->container->instance(Route::class, $route) ; return $route ; } }
  56. // vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.ph p namespace Illuminate\Routing ; class RouteCollection extends AbstractRouteCollectio

    n { /* * * Find the first route matching a given request . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Routing\Rout e * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpExceptio n * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpExceptio n * / public function match(Request $request ) { $routes = $this->get($request->getMethod()) ; // First, we will see if we can find a matching route for this current reques t // method. If we can, great, we can just return it so that it can be calle d // by the consumer. Otherwise we will check for routes with another verb . $route = $this->matchAgainstRoutes($routes, $request) ; return $this->handleMatchedRoute($request, $route) ; } }
  57. // vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.ph p namespace Illuminate\Routing ; class RouteCollection extends AbstractRouteCollectio

    n { /* * * Determine if a route in the array matches the request . * * @return \Illuminate\Routing\Route|nul l * / protected function matchAgainstRoutes(array $routes, $request, $includingMethod = true ) { [$fallbacks, $routes] = collect($routes)->partition(function ($route) { return $route->isFallback ; }) ; return $routes->merge($fallbacks)->first(function (Route $route) use ($request, $includin { return $route->matches($request, $includingMethod) ; }) ; } }
  58. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Route { /*

    * * Determine if the route matches a given request . * * @return boo l * / public function matches(Request $request, $includingMethod = true ) { $this->compileRoute() ; foreach (self::getValidators() as $validator) { if (! $includingMethod && $validator instanceof MethodValidator) { continue ; } if (! $validator->matches($this, $request)) { return false ; } } return true ; } }
  59. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Route { /*

    * * Compile the route into a Symfony CompiledRoute instance . * / protected function compileRoute( ) { if (! $this->compiled) { $this->compiled = $this->toSymfonyRoute()->compile() ; } return $this->compiled ; } public function toSymfonyRoute( ) { return new SymfonyRoute ( preg_replace('/\{(\w+?)\?\}/', '{$1}', $this->uri()), $this->getOptionalParameterNames() , $this->wheres, ['utf8' => true, 'action' => $this->action] , $this->getDomain() ?: '', [], $this->method s ) ; } }
  60. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Route { /*

    * * Determine if the route matches a given request . * * @return boo l * / public function matches(Request $request, $includingMethod = true ) { $this->compileRoute() ; foreach (self::getValidators() as $validator) { if (! $includingMethod && $validator instanceof MethodValidator) { continue ; } if (! $validator->matches($this, $request)) { return false ; } } return true ; } }
  61. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Route { /*

    * * Get the route validators for the instance . * * @return arra y * / public static function getValidators( ) { if (isset(static::$validators)) { return static::$validators ; } // To match the route, we will use a chain of responsibility pattern with th e // validator implementations. We will spin through each one making sure i t // passes and then we will know if the route as a whole matches request . return static::$validators = [ new UriValidator, new MethodValidator , new SchemeValidator, new HostValidator , ] ; } }
  62. // vendor/laravel/framework/src/Illuminate/Routing/Matching/UriValidator.ph p namespace Illuminate\Routing\Matching ; use Illuminate\Http\Request ; use

    Illuminate\Routing\Route ; class UriValidator implements ValidatorInterfac e { /* * * Validate a given rule against a route and request . * * @param \Illuminate\Routing\Route $rout e * @param \Illuminate\Http\Request $reques t * @return boo l * / public function matches(Route $route, Request $request ) { $path = rtrim($request->getPathInfo(), '/') ?: '/' ; return preg_match($route->getCompiled()->getRegex(), rawurldecode($path)) ; } }
  63. // vendor/laravel/framework/src/Illuminate/Routing/Matching/UriValidator.ph ; $regex = '{^/users/(?P<user>[^/]++)$}sDu';

  64. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Route { /*

    * * Determine if the route matches a given request . * * @return boo l * / public function matches(Request $request, $includingMethod = true ) { $this->compileRoute() ; foreach (self::getValidators() as $validator) { if (! $includingMethod && $validator instanceof MethodValidator) { continue ; } if (! $validator->matches($this, $request)) { return false ; } } return true ; } }
  65. // vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.ph p namespace Illuminate\Routing ; class RouteCollection extends AbstractRouteCollectio

    n { /* * * Find the first route matching a given request . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Routing\Rout e * * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpExceptio n * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpExceptio n * / public function match(Request $request ) { $routes = $this->get($request->getMethod()) ; // First, we will see if we can find a matching route for this current reques t // method. If we can, great, we can just return it so that it can be calle d // by the consumer. Otherwise we will check for routes with another verb . $route = $this->matchAgainstRoutes($routes, $request) ; return $this->handleMatchedRoute($request, $route) ; } }
  66. // vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.ph p namespace Illuminate\Routing ; abstract class AbstractRouteCollection {

    protected function handleMatchedRoute(Request $request, $route ) { if (! is_null($route)) { return $route->bind($request) ; } // If no route was found we will now check if a matching route is specified b y // another HTTP verb. If it is we will need to throw a MethodNotAllowed an d // 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 ; } }
  67. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * The route collection instance . * * @var \Illuminate\Routing\RouteCollectionInterfac e * / protected $routes ; /* * * Find the route matching a given request . * * @param \Illuminate\Http\Request $reques t * @return \Illuminate\Routing\Rout e * / protected function findRoute($request ) { $this->current = $route = $this->routes->match($request) ; $this->container->instance(Route::class, $route) ; return $route ; } }
  68. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Dispatch the request to the application . * * @param \Illuminate\Http\Request $reques t * @return \Symfony\Component\HttpFoundation\Respons e * / public function dispatch(Request $request ) { $this->currentRequest = $request ; return $this->dispatchToRoute($request) ; } /* * * Dispatch the request to a route and return the response . * / public function dispatchToRoute(Request $request ) { return $this->runRoute($request, $this->findRoute($request)) ; } }
  69. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Return the response for the given route . * * @param \Illuminate\Http\Request $reques t * @param \Illuminate\Routing\Route $rout e * @return \Symfony\Component\HttpFoundation\Respons e * / protected function runRoute(Request $request, Route $route ) { $request->setRouteResolver(function () use ($route) { return $route ; }) ; $this->events->dispatch(new RouteMatched($route, $request)) ; return $this->prepareResponse($request , $this->runRouteWithinStack($route, $request ) ) ; } }
  70. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Run the given route within a Stack "onion" instance . * / 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(function ($request) use ($route) { return $this->prepareResponse ( $request, $route->run( ) ) ; }) ; }
  71. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Rout e {

    /* * * Run the route action and return the response . * * @return mixe d * / public function run( ) { $this->container = $this->container ?: new Container ; try { if ($this->isControllerAction()) { return $this->runController() ; } return $this->runCallable() ; } catch (HttpResponseException $e) { return $e->getResponse() ; } } }
  72. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Run the given route within a Stack "onion" instance . * / 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(function ($request) use ($route) { return $this->prepareResponse ( $request, $route->run( ) ) ; }) ; }
  73. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Create a response instance from the given value . * * @param \Symfony\Component\HttpFoundation\Request $reques t * @param mixed $respons e * @return \Symfony\Component\HttpFoundation\Respons e * / public function prepareResponse($request, $response ) { return static::toResponse($request, $response) ; } /* * * Static version of prepareResponse . * * @param \Symfony\Component\HttpFoundation\Request $reques t * @param mixed $respons e * @return \Symfony\Component\HttpFoundation\Respons e * / public static function toResponse($request, $response ) { if ($response instanceof Responsable) { $response = $response->toResponse($request) ; }
  74. * / 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 | | 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) ; }
  75. // vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.ph p namespace Illuminate\Foundation\Http ; class Kernel implements KernelContrac

    t { public function handle($request ) { try { $request->enableHttpMethodParameterOverride() ; $response = $this->sendRequestThroughRouter($request) ; } catch (Throwable $e) { $this->reportException($e) ; $response = $this->renderException($request, $e) ; } $this->app['events']->dispatch ( new RequestHandled($request, $response ) ) ; return $response ; } }
  76. Is your pizza being prepared? Route model binding Photo by

    Athena from Pexels
  77. Route::get('/airports/{airport}', [AirportsController::class, ‘show’] ) ->name('airports.show') ;

  78. Route::get('/airports/{airport}', [AirportsController::class, ‘show'] ) ->name(‘airports.show') ; use App\Models\Airport ; class

    AirportsController extends Controlle r { public function show(Airport $airport ) { return $airport ; } } Route::get('/airports/{airport}', function (Airport $airport) { return $airport ; })->name('airports.show') ;
  79. // https://example.com/airports/ 1 Route::get('/airports/{airport}', function (Airport $airport) { // \App\Models\Airpor

    t return $airport ; })->name('airports.show'); // https://example.com/airports/ 1 Route::get('/airports/{airport}', function ($airport) { // 1 return $airport ; })->name('airports.show');
  80. Route::get('users/{username}', function ($name) { return $name ; })->where('username', '[A-Za-z]+')->name('users.show') ;

    Route::get('{twitter}', function ($twitter) { return $twitter ; })->where('twitter', '^@(\w){1,15}$')->name('twitter') ; $ php artisan route:list +--------+----------+------------------+------------+---------+------------+ | Domain | Method | URI | Name | Action | Middleware | +--------+----------+------------------+------------+---------+------------+ | | GET|HEAD | users/{username} | users.show | Closure | web | | | GET|HEAD | {twitter} | twitter | Closure | web | +--------+----------+------------------+------------+---------+------------+
  81. Route::get('users/{id}', [UsersController::class, 'show'] ) ->whereNumber('id' ) ->name('users.show') ; Route::get('users/{username}', [UsersController::class,

    'show'] ) ->whereAlpha('username' ) ->name('users.show') ; Route::get('users/{username}', [UsersController::class, 'show'] ) ->whereAlphaNumeric('username' ) ->name('users.show') ; Route::get('users/{id}', [UsersController::class, 'show'] ) ->whereUuid('id' ) ->name('users.show');
  82. use App\Models\Airport ; class AirportsController extends Controlle r { public

    function show(?Airport $airport = null ) { if ($airport === null) { return Airport::first() ; } return $airport ; } } Route::get(‘/airports/{airport?}', [AirportsController::class, ‘show’] ) ->name('airports.show');
  83. Route::get('/airports/{airport}', [AirportsController::class, 'show'] ) ->name('airports.show' ) ->missing(function (Request $request) {

    return redirect()->route('airports.index') ; });
  84. // https://example.com/airports/AM S Route::get('/airports/{airport:code}', [AirportsController::class, ‘show'] ) ->name('airports.show');

  85. namespace App\Models ; final class Airport extends Mode l {

    use HasFactory ; /* * * Get the route key for the model . * * @return strin g * / public function getRouteKeyName(): strin g { return 'code' ; } } // https://example.com/airports/AM S Route::get('/airports/{airport}', [AirportsController::class, ‘show’] ) ->name('airports.show');
  86. // app/Providers/RouteServiceProvider.ph p namespace App\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Define your route model bindings, pattern filters, etc . * * @return voi d * / public function boot( ) { Route::model('airport', Airport::class) ; Route::model('code', Airport::class) ; } } // https://example.com/airports/AM S Route::get('/airports/{airport}', [AirportsController::class, ‘show’] ) ->name(‘airports.show') ; Route::get('/airports/{code}', [AirportsController::class, ‘show’] ) ->name(‘airports.show’);
  87. // app/Providers/RouteServiceProvider.ph p namespace App\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Define your route model bindings, pattern filters, etc . * * @return voi d * / public function boot( ) { Route::bind(‘airport', function ($value) { return Airport::where('code', $value ) ->orWhere('id', $value ) ->orWhere('uuid', $value ) ->firstOrFail() ; }) ; } }
  88. namespace App\Models ; final class Airport extends Mode l {

    public function resolveRouteBinding($value, $field = null): sel f { return $this->where('code', $value ) ->orWhere('id', $value ) ->orWhere('uuid', $value ) ->firstOrFail() ; } }
  89. // app/Http/Kernel.ph p namespace App\Http; class Kernel extends HttpKerne l

    { /* * * The application's route middleware groups . * * @var arra y * / protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class , \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class , \Illuminate\Session\Middleware\StartSession::class , // \Illuminate\Session\Middleware\AuthenticateSession::class , \Illuminate\View\Middleware\ShareErrorsFromSession::class , \App\Http\Middleware\VerifyCsrfToken::class , \Illuminate\Routing\Middleware\SubstituteBindings::class , ] , 'api' => [ 'throttle:api' , \Illuminate\Routing\Middleware\SubstituteBindings::class , ] , ] ; }
  90. // vendor/laravel/framework/src/Illuminate/Routing/Middeware/SubstituteBindings.ph p namespace Illuminate\Routing\Middleware; class SubstituteBindings { /** *

    Handle an incoming request. */ public function handle($request, Closure $next) { try { $this->router->substituteBindings($route = $request->route()); $this->router->substituteImplicitBindings($route); } catch (ModelNotFoundException $exception) { if ($route->getMissing()) { return $route->getMissing()($request); } throw $exception; } return $next($request); } }
  91. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { 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 ; } /** * Call the binding callback for the given key. */ protected function performBinding($key, $value, $route) { return call_user_func($this->binders[$key], $value, $route); } }
  92. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { 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 ; } /** * Call the binding callback for the given key. */ protected function performBinding($key, $value, $route) { return call_user_func($this->binders[$key], $value, $route); } }
  93. // app/Providers/RouteServiceProvider.ph p namespace App\Providers ; class RouteServiceProvider extends ServiceProvide

    r { /* * * Define your route model bindings, pattern filters, etc . * / public function boot( ) { Route::model('code', Airport::class) ; Route::bind('airport', function ($value) { return Airport::where('code', $value ) ->orWhere('id', $value ) ->orWhere('uuid', $value ) ->firstOrFail() ; }) ; } }
  94. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Add a new route parameter binder . * / public function bind($key, $binder ) { $this->binders[str_replace('-', '_', $key)] = RouteBinding::forCallback ( $this->container, $binde r ) ; } /* * * Register a model binder for a wildcard . * / public function model($key, $class, Closure $callback = null ) { $this->bind($key, RouteBinding::forModel($this->container, $class, $callback)) ; } }
  95. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph d Route::bind('airport', App\Services\AirportBinder::class) ; // Calls the method

    of the clas s Route::bind('airport', ‘App\Services\AirportBinder@parse') ; // Use the callback Route::bind('airport', function ($value) { return Airport::where('code', $value ) ->orWhere('id', $value ) ->firstOrFail() ; });
  96. // vendor/laravel/framework/src/Illuniate/Routing/RouteBinding.ph p namespace Illuminate\Routing ; class RouteBindin g {

    public static function forCallback($container, $binder ) { if (is_string($binder)) { return static::createClassBinding($container, $binder) ; } return $binder ; } protected static function createClassBinding($container, $binding ) { return function ($value, $route) use ($container, $binding) { // If the binding has an @ sign, we will assume it's being used to delimi t // the class name from the bind method name. This allows for binding s // to run multiple bind methods in a single class for convenience . [$class, $method] = Str::parseCallback($binding, 'bind') ; $callable = [$container->make($class), $method] ; return $callable($value, $route) ; } ; } }
  97. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Add a new route parameter binder . * / public function bind($key, $binder ) { $this->binders[str_replace('-', '_', $key)] = RouteBinding::forCallback ( $this->container, $binde r ) ; } /* * * Register a model binder for a wildcard . * / public function model($key, $class, Closure $callback = null ) { $this->bind($key, RouteBinding::forModel($this->container, $class, $callback)) ; } }
  98. // vendor/laravel/framework/src/Illuniate/Routing/RouteBinding.ph p namespace Illuminate\Routing ; class RouteBindin g {

    public static function forModel($container, $class, $callback = null ) { return function ($value) use ($container, $class, $callback) { if (is_null($value)) { return ; } // Try to find the model and return it . $instance = $container->make($class) ; if ($model = $instance->resolveRouteBinding($value)) { return $model ; } // Callback to determine what should happen if model was not found . if ($callback instanceof Closure) { return $callback($value) ; } throw (new ModelNotFoundException)->setModel($class) ; } ; } }
  99. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Add a new route parameter binder . * / public function bind($key, $binder ) { $this->binders[str_replace('-', '_', $key)] = RouteBinding::forCallback ( $this->container, $binde r ) ; } /* * * Register a model binder for a wildcard . * / public function model($key, $class, Closure $callback = null ) { $this->bind($key, RouteBinding::forModel($this->container, $class, $callback)) ; } }
  100. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { 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 ; } /** * Call the binding callback for the given key. */ protected function performBinding($key, $value, $route) { return call_user_func($this->binders[$key], $value, $route); } }
  101. // vendor/laravel/framework/src/Illuminate/Routing/Router.ph p namespace Illuminate\Routing ; class Router implements BindingRegistrar,

    RegistrarContrac t { /* * * Substitute the implicit Eloquent model bindings for the route . * / public function substituteImplicitBindings($route ) { ImplicitRouteBinding::resolveForRoute($this->container, $route) ; } }
  102. // vendor/laravel/framework/src/Illuminate/Routing/ImplicitRouteBinding.ph p namespace Illuminate\Routing ; class ImplicitRouteBindin g {

    public static function resolveForRoute($container, $route ) { $parameters = $route->parameters() ; foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) { if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) { continue ; } $parameterValue = $parameters[$parameterName] ; if ($parameterValue instanceof UrlRoutable) { continue ; } $instance = $container->make(Reflector::getParameterClassName($parameter)) ; $parent = $route->parentOfParameter($parameterName) ; if ($parent instanceof UrlRoutable && in_array($parameterName, array_keys($route- >bindingFields()))) { if (! $model = $parent->resolveChildRouteBinding ( $parameterName, $parameterValue, $route->bindingFieldFor($parameterName ) {
  103. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Rout e {

    /** * Get the parameters that are listed in the route / controller signature. * * @param string|null $subClass * @return array */ public function signatureParameters($subClass = null) { return RouteSignatureParameters::fromAction($this->action, $subClass); } }
  104. // vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php namespace Illuminate\Routing; class RouteSignatureParameters { public static function

    fromAction(array $action, $subClass = null) { $callback = RouteAction::containsSerializedClosure($action) ? unserialize($action['uses'])->getClosure() : $action['uses']; $parameters = is_string($callback) ? static::fromClassMethodString($callback) : (new ReflectionFunction($callback))->getParameters(); return is_null($subClass) ? $parameters : array_filter($parameters, function ($p) use ($subClass) { return Reflector::isParameterSubclassOf($p, $subClass); }); } protected static function fromClassMethodString($uses) { [$class, $method] = Str::parseCallback($uses); if (! method_exists($class, $method) && Reflector::isCallable($class, $method)) { return []; } return (new ReflectionMethod($class, $method))->getParameters(); } }
  105. // vendor/laravel/framework/src/Illuminate/Routing/RouteSignatureParameters.php namespace Illuminate\Routing; class RouteSignatureParameters { public static function

    fromAction(array $action, $subClass = null) { $callback = RouteAction::containsSerializedClosure($action) ? unserialize($action['uses'])->getClosure() : $action['uses']; $parameters = is_string($callback) ? static::fromClassMethodString($callback) : (new ReflectionFunction($callback))->getParameters(); return is_null($subClass) ? $parameters : array_filter($parameters, function ($p) use ($subClass) { return Reflector::isParameterSubclassOf($p, $subClass); }); } protected static function fromClassMethodString($uses) { [$class, $method] = Str::parseCallback($uses); if (! method_exists($class, $method) && Reflector::isCallable($class, $method)) { return []; } return (new ReflectionMethod($class, $method))->getParameters(); } }
  106. { $parameters = $route->parameters() ; foreach ($route->signatureParameters(UrlRoutable::class) as $parameter) {

    if (! $parameterName = static::getParameterName($parameter->getName(), $parameters)) { continue ; } $parameterValue = $parameters[$parameterName] ; if ($parameterValue instanceof UrlRoutable) { continue ; } $instance = $container->make(Reflector::getParameterClassName($parameter)) ; $parent = $route->parentOfParameter($parameterName) ; if ($parent instanceof UrlRoutable && in_array($parameterName, array_keys($route->bindingFields()))) { if (! $model = $parent->resolveChildRouteBinding ( $parameterName, $parameterValue, $route->bindingFieldFor($parameterName ) )) { throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]) ; } } elseif (! $model = $instance->resolveRouteBinding($parameterValue, $route- >bindingFieldFor($parameterName))) { throw (new ModelNotFoundException)->setModel(get_class($instance), [$parameterValue]) ; } $route->setParameter($parameterName, $model) ; } }
  107. // vendor/laravel/framework/src/Illuminate/Routing/Middeware/SubstituteBindings.ph p namespace Illuminate\Routing\Middleware ; class SubstituteBinding s {

    public function handle($request, Closure $next ) { try { $this->router->substituteBindings($route = $request->route()) ; $this->router->substituteImplicitBindings($route) ; } catch (ModelNotFoundException $exception) { if ($route->getMissing()) { return $route->getMissing()($request) ; } throw $exception ; } return $next($request) ; } }
  108. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Rout e {

    /* * * Run the route action and return the response . * * @return mixe d * / public function run( ) { $this->container = $this->container ?: new Container ; try { if ($this->isControllerAction()) { return $this->runController() ; } return $this->runCallable() ; } catch (HttpResponseException $e) { return $e->getResponse() ; } } }
  109. // vendor/laravel/framework/src/Illuminate/Routing/Route.ph p namespace Illuminate\Routing ; class Rout e {

    protected function runController() { return $this->controllerDispatcher()->dispatch( $this, $this->getController(), $this->getControllerMethod() ); } public function getController() { if (! $this->controller) { $class = $this->parseControllerCallback()[0]; $this->controller = $this->container->make(ltrim($class, '\\')); } return $this->controller; } protected function getControllerMethod() { return $this->parseControllerCallback()[1]; } protected function parseControllerCallback() { return Str::parseCallback($this->action['uses']); } }
  110. // vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php namespace Illuminate\Routing; use Illuminate\Container\Container; use Illuminate\Routing\Contracts\ControllerDispatcher as ControllerDispatcherContract;

    class ControllerDispatcher implements ControllerDispatcherContract { use RouteDependencyResolverTrait; /** * Dispatch a request to a given controller and method. */ public function dispatch(Route $route, $controller, $method) { $parameters = $this->resolveClassMethodDependencies( $route->parametersWithoutNulls(), $controller, $method ); if (method_exists($controller, 'callAction')) { return $controller->callAction($method, $parameters); } return $controller->{$method}(...array_values($parameters)); } }
  111. Is your pizza on its way? Router use case Photo

    by Lucian Alexe on Unsplash
  112. { "order": "/order/vendor/dominos/pizza/hawaii" , "message": { "price": "10.80" , "delivery_time":

    "2021-03-17 19:10:00" , "options": [ "no-pineapple " ] } }
  113. class OrdersController extends Controlle r { public function store(Request $request

    ) { $pattern = '/order/vendor/{vendor}/pizza/{pizza}' ; $message = json_decode($request->input('message'), true) ; $parameters = $this->getRouteParametersForPattern($message['order'], $pattern) ; $vendor = Vendor::where('key', $parameters['vendor'])->firstOrFail() ; $pizza = Pizza::where('key', $parameters['pizza'])->firstOrFail(); } } "order": "/order/vendor/dominos/pizza/hawaii",
  114. "order": "/order/vendor/dominos/pizza/hawaii", $pattern = '/order/vendor/{vendor}/pizza/{pizza}'; private function getRouteParametersForPattern(string $url, string

    $pattern): arra y { $compiledRoute = RouteCompiler::compile(new Route($pattern)) ; $matches = [] ; preg_match_all($compiledRoute->getRegex(), $url, $matches) ; $parameters = [] ; foreach ($compiledRoute->getVariables() as $variable) { $parameters[$variable] = $matches[$variable][0] ; } return $parameters ; }
  115. private function getRouteParametersForPattern(string $url, string $pattern): arra y { $compiledRoute

    = RouteCompiler::compile(new Route($pattern)) ; $matches = [] ; preg_match_all($compiledRoute->getRegex(), $url, $matches) ; $parameters = [] ; foreach ($compiledRoute->getVariables() as $variable) { $parameters[$variable] = $matches[$variable][0] ; } return $parameters ; } "order": "/order/vendor/dominos/pizza/hawaii", $pattern = '/order/vendor/{vendor}/pizza/{pizza}'; $regex = "{^/order/vendor/(?P<vendor>[^/]++)/pizza/(?P<pizza>[^/]++)$}sD" ; $matches = [ 'vendor' => [ 'dominos' , ] , 'pizza' => [ 'margherita' , ] , ];
  116. class OrdersController extends Controlle r { public function store(Request $request

    ) { $pattern = '/order/vendor/{vendor}/pizza/{pizza}' ; $message = json_decode($request->input('message'), true) ; $parameters = $this->getRouteParametersForPattern($message['order'], $pattern) ; $vendor = Vendor::where('key', $parameters['vendor'])->firstOrFail() ; $pizza = Pizza::where('key', $parameters['pizza'])->firstOrFail(); } } "order": "/order/vendor/dominos/pizza/hawaii",
  117. { "topic": "/windpark/2/turbine/5/sensor/shadow_flicker" , "message": { "datetime":"2021-17-03T15:47:14+00:00" , "status": tru

    e } }
  118. final class Shadow extends Messag e { public string $type

    = MessageTypes::TYPE_SHADOW_FLICKER ; protected string $routePattern = '/windpark/{windparkId}/turbine/{turbineId}/sensor/shadow_flicker' ; public function validate(): Messag e { if (! is_bool($this->message->status)) { throw new Exception('Value could not be validated') ; } return $this ; } public function isSameStatus($status): boo l { return (bool) $status === $this->message->status ; } }
  119. Did your pizza already arrive? Best practices Photo by Vita

    Marija Murenaite on Unsplash
  120. // Don't do thi s Route::name('teams.')->group(function () { Route::group(['prefix' =>

    'team'], function () { Route::get('/', [TeamsController::class, 'index'])->middleware('auth')->name('index') ; Route::get('/create', [TeamsController::class, 'create'])->middleware('auth')->name('create') ; Route::post('/', [TeamsController::class, 'store'])->middleware('auth')->name('store') ; Route::get('/{team}', [TeamsController::class, 'show'])->middleware('auth')->name('show') ; Route::get('/{team}/edit', [TeamsController::class, 'edit'])->middleware('auth')->name('edit') ; Route::put('/{team}', [TeamsController::class, 'update'])->middleware('auth')->name('update') ; Route::delete('/{team}', [TeamsController::class, 'destroy'])->middleware('auth')->name('destroy') ; }) ; }); // Instead do thi s Route::get('teams', [TeamsController::class, 'index'])->name('teams.index') ; Route::middleware('auth')->group(function () { Route::get('teams/create', [TeamsController::class, 'create'])->name('teams.create') ; Route::post('teams', [TeamsController::class, 'store'])->name('teams.store') ; Route::get('teams/{team}', [TeamsController::class, 'show'])->name('teams.show') ; Route::get('teams/{team}/edit', [TeamsController::class, 'edit'])->name('teams.edit') ; Route::put('teams/{team}', [TeamsController::class, 'update'])->name('teams.update') ; Route::delete('teams/{team}', [TeamsController::class, 'destroy'])->name('teams.destroy') ; });
  121. // app/Providers/RouteServiceProvider.php namespace App\Providers; class RouteServiceProvider extends ServiceProvider { /**

    * Define your route model bindings, pattern filters, etc. */ public function boot() { $this->routes(function () { Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); Route::middleware(['web', 'can:admin']) ->namespace($this->namespace) ->group(base_path('routes/admin.php')); }); } }
  122. // app/Providers/RouteServiceProvider.php namespace App\Providers; class RouteServiceProvider extends ServiceProvider { /**

    * Define your route model bindings, pattern filters, etc. */ public function boot() { $this->routes(function () { if (config('app.api') === true) { Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); } else { Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); } }); } }
  123. // app/Providers/RouteServiceProvider.php namespace App\Providers; class RouteServiceProvider extends ServiceProvider { /**

    * Define your route model bindings, pattern filters, etc. */ public function boot() { Route::model('country', Country::class); Route::bind('airport', function ($value, $route) { return Airport::where('country_id', $route->parameter('country')) ->where('code', $value) ->firstOrFail(); }); } }
  124. // Doesn’t work as expected Route::get('/users/{user}', [UsersController::class, 'show'])->name('users.show'); Route::get('/users/create', [UsersController::class,

    'create'])->name('users.create'); // Works as expected Route::get('/users/create', [UsersController::class, 'create'])->name('users.create'); 
 Route::get('/users/{user}', [UsersController::class, 'show'])->name('users.show');
  125. class SomeMiddlewar e { public function handle($request, Closure $next )

    { // App\Model\Use r $request->route(‘user') ; return $next($request) ; } }
  126. $ php artisan route:cache Route cache cleared! Routes cached successfully!

  127. Ok, one more pizza Photo by Katerina Holmes from Pexels

    Final pizza! Promised!
  128. None
  129. Enjoy your pizza! Thank you 🍕