Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ntbutler-nbcs's avatar

ntbutler-nbcs liked a comment+100 XP

4mos ago

First, you can define which field will be treated as key name for model binding in routes: https://laravel.com/docs/12.x/routing#customizing-the-default-key-name

But this will change key for all your routes, even your internal, so be careful:

// User model

public function getRouteKeyName(): string
{
    return 'sis_id';
}

Second, you can group routes with route name prefix along with other grouping (you can have nested grouping of unlimited levels):

Route::prefix('user.by_sis_id')->group(function () {
    Route::get('user', [UserController::class, 'show'])->name('.show');
    Route::put('user', [UserController::class, 'update'])->name('.update');
    // ....
});

Third, you can have Route::apiResource() to replace all your show/update/destroy... routes:

Route::prefix('user.by_sis_id')->group(function () {
    Route::apiResource('user', UserController::class);
});
ntbutler-nbcs's avatar

ntbutler-nbcs liked a comment+100 XP

4mos ago

you can accept optional parameters in the route, and the use match in the controller. You don't have to use route model binding.

If the second parameter is null, then the first must be the user_id.

Match on the first parameter can be used to check which column to use, or to return an error if no match.

ntbutler-nbcs's avatar

ntbutler-nbcs started a new conversation+100 XP

4mos ago

Hi all!

I'm developing an API for a project, and would like to try to replicate a feature I've used on another site where the property that is used in the route model binding can be set dynamically by the party calling the API.

For context, the API I'm looking to replicate this feature with is the Canvas LMS API, specifically with the SIS ID feature that they have implemented. In short, if they have a GET User API endpoint of https://site.url/api/users/, that same endpoint also will be able to search for and return a user via a secondary id field "sis_user_id", where that field can be a unique value managed by the client (for example using an "employee id" that they may have, or maybe the email address). So, the client can query the endpoint with a slightly different URL like https://site.url/api/users/sis_user_id:<employeeID> and get the same result, without needing to know the internal ID of the user first.

I have managed to get a solution working by defining a route prefix group with each specific route to define the sis_user_id routes listed in that group, and then adding the normal apiResource route for the user controller after that. It works, but I think it could be cleaner, especially as the number of API routes grow.

Route::group(['prefix' => 'v1', 'namespace' => 'App\Http\Controllers\Api\v1', 'middleware' => 'auth:sanctum'], function() {
    Route::prefix('user')->group(function () {
        Route::get   ('sis_user_id:{user:sis_id}', [UserController::class, 'show'])->name('user.by_sis_id.show');
        Route::put   ('sis_user_id:{user:sis_id}', [UserController::class, 'update'])->name('user.by_sis_id.update');
        Route::patch ('sis_user_id:{user:sis_id}', [UserController::class, 'update'])->name('user.by_sis_id.update');
        Route::delete('sis_user_id:{user:sis_id}', [UserController::class, 'destroy'])->name('user.by_sis_id.destroy');
    });
    Route::apiResource('user', UserController::class);
});

Is there a cleaner way to achieve this currently in Laravel (realising that it's not really a widely-used methodology that I've seen around)? I really like the idea of this API feature, meaning that the internal ID's of objects don't need to be tracked/known by end clients, which can simplify the way they manage and query resources in my sites and also help minimise the number of API requests that my sites would need to handle.

Cheers!