I saw a recent question about the best way to set up a route that would allow passing a ULID for one of two different models (job and referrer).
Because it's a ULID and not a numeric integer, there would be no overlap in IDs between the two models, so you could query the Job
model first, and if it's not found, query the Referrer
model.
Putting aside whether this is a good idea or not, I thought it would be fun to see how I would set this up.
While you could handle this logic yourself within the controller, I really like leveraging framework features as much as possible. Could we get Laravel's route model binding to handle this use case?
Yes! By using the RouteServiceProvider
, we can register an explicit model binding with our desired logic:
// app/Providers/RouteServiceProvider.php
public function boot()
{
Route::bind('jobOrReferrer', function ($value) {
$job = Job::find($value);
return $job ?? Referrer::findOrFail($value);
});
}
Then we could register a route like this:
// routes/web.php
Route::get('share/{jobOrReferrer}', [Controllers\ShareController::class, 'show'])->name('share.show');
And then our controller action can use a union type as a type-hint, and our model will be automatically injected by Laravel:
// app/Http/Controllers/ShareController.php
public function show(Job|Referrer $jobOrReferrer)
{
// do something with your model...
}
Here to help,
Joel
P.S. Have a question of your own? Hit reply and ask your question or set up a time to pair.