Last active
October 18, 2022 07:42
-
-
Save sebastiaanluca/d61e9e2bc874615f82cfd679dee8edce to your computer and use it in GitHub Desktop.
Apply late route model binding. See https://github.com/laravel/framework/issues/6118#issuecomment-149951364 for more info.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Http; | |
use Illuminate\Foundation\Http\Kernel as HttpKernel; | |
class Kernel extends HttpKernel | |
{ | |
// Add the trait | |
use LateRouteBinding; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Http; | |
trait LateRouteBinding | |
{ | |
/** | |
* @var array | |
*/ | |
public static $lateBindings = []; | |
// Didn't know where else to put this, since we have no (variable) control over the internal Router class. | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
namespace App\Providers; | |
use App\Http\Kernel; | |
use Illuminate\Routing\ImplicitRouteBinding; | |
use Illuminate\Routing\RouteBinding; | |
use Illuminate\Support\Facades\Route; | |
use Illuminate\Support\ServiceProvider; | |
class RouteMacroServiceProvider extends ServiceProvider | |
{ | |
/** | |
* Register the application's response macros. | |
* | |
* @return void | |
*/ | |
public function boot() | |
{ | |
Route::macro('bindLateModel', function ($key, $class, Closure $callback = null) { | |
$this->bindLate($key, RouteBinding::forModel($this->container, $class, $callback)); | |
}); | |
Route::macro('bindLate', function ($key, $binder) { | |
Kernel::$lateBindings[$key] = RouteBinding::forCallback( | |
$this->container, $binder | |
); | |
}); | |
Route::macro('substituteLateBindings', function ($route) { | |
foreach ($route->parameters() as $key => $value) { | |
if (isset(Kernel::$lateBindings[$key])) { | |
$route->setParameter($key, $this->performLateBinding($key, $value, $route)); | |
} | |
} | |
return $route; | |
}); | |
Route::macro('substituteLateImplicitBindings', function ($route) { | |
ImplicitRouteBinding::resolveForRoute($this->container, $route); | |
}); | |
Route::macro('performLateBinding', function ($key, $value, $route) { | |
return call_user_func(Kernel::$lateBindings[$key], $value, $route); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Middleware; | |
use Closure; | |
use Illuminate\Contracts\Routing\Registrar; | |
class SubstituteLateBindings | |
{ | |
/** | |
* The router instance. | |
* | |
* @var \Illuminate\Contracts\Routing\Registrar | |
*/ | |
protected $router; | |
/** | |
* Create a new bindings substitutor. | |
* | |
* @param \Illuminate\Contracts\Routing\Registrar $router | |
* | |
* @return void | |
*/ | |
public function __construct(Registrar $router) | |
{ | |
$this->router = $router; | |
} | |
/** | |
* Handle an incoming request. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @param \Closure $next | |
* | |
* @return mixed | |
*/ | |
public function handle($request, Closure $next) | |
{ | |
$this->router->substituteLateBindings($route = $request->route()); | |
$this->router->substituteLateImplicitBindings($route); | |
return $next($request); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
Route::group(['middleware' => ['auth', MiddlewareThatAppliesGlobalScopesFYI::class, SubstituteLateBindings::class]], function () { | |
// Your routes | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Short howto:
LateRouteBinding
trait to your application's HTTP kernelRouteMacroServiceProvider
in yourconfig/app.php
fileSubstituteLateBindings
middleware to your routes$this->bindLate()
method to explicitly bind your modelsOptionally you could remove the default
SubstituteBindings
middleware from your Kernel so all bindings, even implicit ones, are done after.