Mohamed Allam
Laravel Example

Laravel Example

Laravel Route Model binding using Multiple keys

Laravel Route Model binding using Multiple keys

Laravel tutorial on how to retrieve a model instance using its id or slug, leveraging Laravel route model binding

Mohamed Allam's photo
Mohamed Allam

Published on Sep 9, 2021

3 min read

Subscribe to my newsletter and never miss my upcoming articles

Laravel ships with route model binding, the abilty to pass data through the get request, Laravel out of the box, captures the value, and find the matched model instance.

Lets assume we have the famous task list app, where we can see task on the index page of our website but we can visit each task by its Id.

We setup Laravel

Installation of Laravel

Laravel new Tasklist

We have to create a database, and change credentials to connect to the database through our .env file.

I use sqlite database. so I run the command:

touch database/database.sqlite

Then we specify the driver on our .env file:

DB_CONNECTION=sqlite

Our project world

We create a model Task, with migration, factory, seeder and resourceful controller.

php artisan make:model Task -a
Model created successfully.
Factory created successfully.
Created Migration: 2021_09_09_084744_create_tasks_table
Seeder created successfully.
Controller created successfully.

Lets first create some tasks to work with:

Given a task has only a title, in our tasks migration file, we add the title to our table, it ca

Schema::create('tasks', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('slug')->unique();
            $table->timestamps();
        });

We run the command to migrate our databse.

php artisan migrate
// tables migrated successfully

In our TaskFactory, we give it what it should return as a dummy data. we create a fake sentence,

return [
    'title' => $title = $this->faker->sentence(),
    'slug' => \Illuminate\Support\Str::slug($title),
    ];

Lets give our seeder the number (10) of factories we want to create

 public function run()
    {
        \App\Models\Task::factory(10)->create();
    }

In our DatabaseSeeder.php we have to call the TaskSeeder Class

public function run()
    {
        $this->call([
            TaskSeeder::class,
        ]);
       // we can directly add our task seeder here \App\Models\Task::factory(10)->create();
    }

Lets seed our data.

php artisan db:seed

We check through the browser

To see all our tasks in our routes file we

use App\Http\Controllers\TaskController;

Route::get('/', [TaskController::class, 'index']);

In our TaskController

public function index()
{
    return \App\Models\Task::all();
}

now we visit the index of our website

tasklist.test

This will print out all our tasks, we can see the slug and Id, of course.

Route Model binding

Now in our routes folder, web.php file we get the tasks using route model binding defaults, which is the ID.

Route::get('/{task}', [TaskController::class, 'show']);

In our controller show method, we return the task, Laravel will automatically give as the task instance using the ID, from the URI given.

public function show(Task $task)
{
    return $task;
}

Route Model binding using multiple keys

Lets assume for whatever reason, we want the tasks either using the ID, or a slug as well,

We go to our AppServiceProvider.php in our Providers folder.

\Route::bind('task', function ($value){
    return \App\Models\Task::where('slug', $value)->orWhere( function ($query) use ($value){
        if (is_numeric($value)){
            $query->where('id', $value);
        }
    })->firstOrFail();
});

Now whenever we visit tasks through id tasklist.test/1 or we visit by slug tasklist.test/facere-provident-corrupti-quibusdam-magnam we get the same result.

id: "1"
title:    "Facere provident corrupti quibusdam magnam."
slug:    "facere-provident-corrupti-quibusdam-magnam"
 
Share this
Proudly part of