To achieve the desired functionality where you can call route('post.show', $post) and have the {organization} parameter automatically derived from the $post object, you can use Laravel's route model binding and custom URL generation logic. Here's a step-by-step solution:
-
Custom Route Key Binding:
First, ensure that your
Postmodel has a relationship with theOrganizationmodel. Then, you can define a custom route key binding for thePostmodel to automatically include the organization in the URL.In your
RouteServiceProvider, you can override thebootmethod to define a custom binding:use Illuminate\Support\Facades\Route; use App\Models\Post; public function boot() { parent::boot(); Route::bind('post', function ($value) { return Post::where('id', $value)->with('organization')->firstOrFail(); }); } -
Custom URL Generation Logic:
You can extend the
UrlGeneratorto customize how URLs are generated for your routes. This involves creating a custom service provider to override the default URL generator.First, create a custom URL generator:
namespace App\Routing; use Illuminate\Routing\UrlGenerator as BaseUrlGenerator; class UrlGenerator extends BaseUrlGenerator { public function route($name, $parameters = [], $absolute = true) { if (isset($parameters[0]) && $parameters[0] instanceof \App\Models\Post) { $post = $parameters[0]; $parameters = [$post->organization_id, $post->id]; } return parent::route($name, $parameters, $absolute); } } -
Register the Custom URL Generator:
In your
AppServiceProvideror a custom service provider, bind your custom URL generator:namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Routing\UrlGenerator; class AppServiceProvider extends ServiceProvider { public function register() { $this->app->singleton('url', function ($app) { return new UrlGenerator($app['router']->getRoutes(), $app->rebinding( 'request', $this->requestRebinder() )); }); } protected function requestRebinder() { return function ($app, $request) { $app['url']->setRequest($request); }; } } -
Update Your Routes:
Ensure your routes are defined to accept both
{organization}and{post}parameters:Route::get('/{organization}/post/{post}', [PostController::class, 'show'])->name('post.show');
With these changes, you should be able to call route('post.show', $post) and have the {organization} parameter automatically derived from the $post object. This approach keeps your route definitions clean and allows for easy integration into a package.