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

Userinfo's avatar

Problem with my route slug

Hello everyone !

I have a problem with my route. When I put the slug in parameter I get a 404 error

Knowing that in my database the slug field is unique, not null, not empty

My Model

     /**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

My Controller

 public function test(Post $post)
    {   
       return view('visit.one-post', compact('post'));
    }

My route

Route::get('/posts/{post}',[PostController::class, 'test'], function () {
    return view('visit.one-post);
})->name('test');

My view

<a href="{{ route('test',$post)}}">
                            <button class="btn btn-info" type="submit">See post</button>
                        </a>

When I delete the line below my route uses id as a parameter and it works I return my view with the correct data

public function getRouteKeyName ()
{
    return 'slug';
}

So I come to you because I don't know where my mistake came from Thank you in advance I wish you all a good day: D

0 likes
33 replies
bobbybouwmann's avatar

This is the problem

<a href="{{ route('test',$post)}}">

Laravel doesn't know it needs to provide the slug here as the key for the route. Try this instead

<a href="{{ route('test', $post->slug) }}">
3 likes
Userinfo's avatar

@bobbybouwmann Thanks for your quick answer ! Thanks for the help

I also tried but I have a 404 page, cannot access the view :/

webrobert's avatar

@userinfo, i skip the keyname method and just use...

Route::get('/posts/{post:slug}',[PostController::class, 'test'], function () {
 ...
1 like
Userinfo's avatar

Thank you for the answer , I also tried this is what I tried:

Route :: get ('/posts/{post:slug}', [PostController :: class, 'test'], function () {
Route :: get ('/posts/{post}', [PostController::class, 'test'], function () {
Route :: get ('/posts/{slug}', [PostController :: class, 'test'], function () {
 <a href=" route('test',$post-> slug)}} ">
       <button class = "btn btn-info" type = "submit"> See post </button>
 </a>
 <a href="route('test',$post)}} ">
       <button class = "btn btn-info" type = "submit"> See post </button>
 </a>
 <a href="route('test',$slug)}} ">
       <button class = "btn btn-info" type = "submit"> See post </button>
 </a>

Nothing works , The question I ask myself is: why does it work with the id in parameter and with the slug it does not work ?

webrobert's avatar

@Userinfo,

also, i don't think you want a closure here...

Route::get('/posts/{post}',[PostController::class, 'test'], function () {
    return view('visit.one-post);
})->name('test');

instead...

Route::get('/posts/{post:slug}', [PostController::class, 'test'])->name('test');
1 like
Userinfo's avatar

Thank you for the help, I have tried everything, nothing works I will continue my research Do I have to match in my controller and specify :

public function test($param)
{
   $ post = Post :: where ('id', $ param)
           -> orWhere ('slug', $ param)
           -> firstOrFail ();
}
webrobert's avatar

@Userinfo, here...

 <a  href="{{ route('test', $post->slug) }}"> see post </a>
Route::get('/posts/{post:slug}', [PostController::class, 'test'])->name('test');
public function test(Post $post)
{
    dd($post);
}
1 like
Userinfo's avatar

@webrobert Thank's :) I just tried this on page 404: s

In my a href, I still recover my post / post-test-1 slug post / post-test-2 But when I clicked I got the 404 error: /

nacha's avatar

@userinfo try this in controller:

public function test($slug)
    {
        $post = Post::where('slug', $slug)->first();

        return view('visit.one-post', compact('post'));
    }

route:

Route::get('/posts/{slug}', [PostController::class, 'test'])->name('test');

blade:

 <a href="{{ route('test' , $post-> slug)}} ">
       <button class = "btn btn-info" type = "submit"> See post </button>
 </a>

1 like
Userinfo's avatar

@nacha It does not work the problem must come from elsewhere, I have reviewed the controller, the view and the web.php but nothing works thanks for the help

Snapey's avatar

Its not sufficient to just look at the one route. The whole web.php needs to be reviewed

You could have an earlier route that is matching

1 like
Userinfo's avatar

Thank you all for your help ! I tried and even isolated the files (create a single route, a single controller ... but it doesn't work) I would however like an explanation please on

/ **
 * Get the route key for the model.
 *
 * @return string
 * /
public function getRouteKeyName ()
{
    return 'slug';
}

If I put this line my edit urls with id as a parameter on my route no longer work, how can I make it so that I can use the id and the slug as the url parameter and it works for both? thank you

Snapey's avatar

@Userinfo You already have that answer earlier from webrobert;

Route::get('/posts/{post:slug}', [PostController::class, 'test'])->name('test');
1 like
Snapey's avatar

I also asked for you to show the routes file. There is a good chance that your 404 is coming from one of these

urls with id as a parameter on my route

1 like
Userinfo's avatar

@Snapey

Route::get('/', function () {
    return view('welcome');
});

Route::get('index', function () {
    return view('index');
});

Route::get('admin/home', [HomeController::class, 'adminHome'])->name('admin.home')->middleware('is_admin');
Route::get('home', [HomeController::class, 'index'])->name('home');

Route::get('/admin/dashboard', [UserController::class, 'user_info'], function () {
    return view('dashboard');
})->name('dashboard')->middleware(['is_admin']);

Route::delete('/admin/dashboard/user/{id}', [UserController::class, 'destroy'], function () {
    return view('dashboard');
})->name('destroy_user')->middleware(['is_admin']);


Route::get('/admin/addpost/{id}', [UserPostController::class, 'create'], function () {
    return view('addpost');
})->name('create')->middleware(['is_admin']);


Route::post('/admin/addpost/create', [UserPostController::class, 'store'], function () {
    return view('addpost');
})->name('store')->middleware(['is_admin']);


Route::get('/visit/post',[PostController::class, 'mes_posts'], function () {
    return view('visit.mes-posts');
})->name('posts');

Route::get('/visit/post/{post}/edit',[PostController::class,'edit'], function () {
    return view('visit.edit-post');
})->name('edit');

Route::put('/visit/edit/{post}',[PostController::class, 'update'], function () {
    return view('visit.edit-post');
})->name('posts.update')->middleware(['is_admin']);

Route::get('/posts',[PostController::class, 'show'], function () {
    return view('visit.posts');
})->name('show.posts');

// Route::get('/posts/{post}',[PostController::class, 'test'], function () {
//     return view('visit.one-post');
// })->name('test');

Route::get('/posts/{post:slug}', [PostController::class, 'test'])->name('test');
Snapey's avatar

@Userinfo looks ok

So if you type into your browser address bar website.test/posts/a-valid-slug

what happens

johnDoe220's avatar

you must send slug data

<a href="{{ route('test',$post->slug)}}">
        <button class="btn btn-info" type="submit">See post</button>
</a>
1 like
johnDoe220's avatar

@Userinfo you send secound view first into route

Route::get('/posts/{post}',[PostController::class, 'test'], function () {
    return view('visit.one-post);
})->name('test');

and controller

public function test(Post $post)
    {   
       return view('visit.one-post', compact('post'));
    }

this true:

Route::get('/posts/{post}',[PostController::class, 'test'])->name('test');
1 like
johnDoe220's avatar

@Userinfo If not, use another method, although I think this code will work because I have already used this structure in my project.

public function test($slug)
    {   
	$post = Post::where('slug', $slug)->first();
       return view('visit.one-post', compact('post'));
    }
1 like
johnDoe220's avatar

@Userinfo Have you noticed that in the web.php file You do not have exactly the same path as this route I mean you do not have another path hip in this file that is exactly like this?

Route :: get ('posts/{post}')

After considering all these possibilities, this can be the only reason for the 404 error

1 like
Userinfo's avatar

@johnDoe220 No I have this type of path that works I have as an example:

Route :: get ('/ visit / post / {post} / edit', [PostController :: class, 'edit'], function () {
   return view ('visit.edit-post');
}) -> name ('edit');

It works perfectly but the {post} is actually the id My road will therefore be

localhost / visit / post / 1 / edit
Userinfo's avatar

Ok thank you, but I have this first, or I display all my posts

 public function show ()
    {
        $ posts = Post :: all ();

        return view ('visit.posts', [
            'posts' => $ posts,
        ]);
    }

Then I enter my info in my view

@section ('content')
<div class = "py-12">
    <div class = "max-w-7xl mx-auto sm: px-6 lg: px-8">
        <div class = "bg-white overflow-hidden shadow-sm sm: rounded-lg">
            <div class = "p-6 bg-white border-b border-gray-200">
                <div class = "card-deck">
                </thead>
                @forelse ($ posts as $ post)

                @empty
                @endforelse
                @foreach ($ posts as $ post)
                    
                    <div class = "card">
                        <div class = "embed-responsive embed-responsive-16by9">
                           <img alt = "Card image cap" class = "card-img-top embed-responsive-item" src = "{{asset ('storage /'.$ post-> picture)}}" />
                        </div>
                        <div class = "card-block">
                          <h4 class = "card-title"> {{$ post ['name']}} </h4>
                          <p class = "card-text"> {{substr ($ post ['description'], 0, 80). "". "..."}} </p>
                          <a href=" route('test',$post-> slug)}} ">
                            <button class = "btn btn-info" type = "submit"> See the post</button>
                          </a>
                        </div>
                      </div>
                @endforeach
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

And I have my controller that you gave me

 public function test ($ slug)
    {
$ post = Post :: where ('slug', $ slug) -> first ();
       return view ('visit.one-post', compact ('post'));
    }

The controller slug parameter

test ($ slug)

How do I integrate it into my route and into my view href ?

johnDoe220's avatar

@Userinfo You did not put this in href

{{
<a href="{{route('test',$post->slug)}} ">
                            <button class = "btn btn-info" type = "submit"> See the post</button>
                          </a>
1 like
Userinfo's avatar

@johnDoe220 Unfortunately no: / But I ask myself a question as I am a novice in laravel, I have

public function getRouteKeyName()
{
    return 'slug';
}

Do i have to use this ? Because sometimes I want to use the id and sometimes the slug depending on the functions I use. I noticed that when I put this line of code my id parameter in my routes no longer works. By putting slug my slug parameter should work but it is not the case

johnDoe220's avatar

@Userinfo Yes, when you use this function, every post you call will be fetched according to it in the data table, otherwise if you do not set it by default, it will use the ID as the identifier and finally fetch the data.

1 like
Userinfo's avatar

@johnDoe220 Thank you so much, is it still possible to use the id and the slug for various functions? That is to say to circumvent this problem in the case where I would like for example

visit/post/edit/1
and
visit/posts/my-first-post
johnDoe220's avatar
Level 8

@Userinfo look If you want to use the root binding model method, you must use this method in your method

public function test(Post $post)
{
	return view('test', compact('post'));
}
// this method use default id for fetch data from post table
// route example for read single post - Route::get('posts/{post}', [postsController::class, 'test'])->name('posts.single');
// now how to fetch view - <a href="{{ route('posts.single', $post->id) }}">mor info</a>

if you want use route model binding for slug, you must this methods

public function getRouteKeyName()
{
	return 'slug';
}
// this method must be write post model
// route example for read single post with slug - Route::get('posts/{post}', [postsController::class, 'test'])->name('posts.single');
// now how to fetch view - <a href="{{ route('posts.single', $post->slug) }}">mor info</a>

edit with id without route model binding

public function edit($id)
{
	$post = Post::where('id', $id)->first();
	return view('test', compact('post'));
}

Route::get('posts/{anything}', [postsController::class, 'edit'])->name('posts.edit);
// href into view - <a href="{{ route('posts.edit', $post->id) }}">edit</a>

edit with id with route model binding

public function edit(Post $post)
{
	return view('test', compact('post'));
}

Route::get('posts/{post}', [postsController::class, 'edit'])->name('posts.edit);
// href into view - <a href="{{ route('posts.edit', $post->id) }}">edit</a>

edit with slug without route model binding

public function edit($slug)
{
	$post = Post::where('slug', $slug)->first();
	return view('test', compact('post'));
}

Route::get('posts/{anything}', [postsController::class, 'edit'])->name('posts.edit);
// href into view - <a href="{{ route('posts.edit', $post->slug) }}">edit</a>

edit with slug with route model binding

public function edit(Post $post)
{
	return view('test', compact('post'));
}

Route::get('posts/{post}', [postsController::class, 'edit'])->name('posts.edit);
// href into view - <a href="{{ route('posts.edit', $post->slug) }}">edit</a>
// And I emphasize that you should use this structure in the model except for the ID with anything else that you want to read the post
For example, here I want to read the post using the slag column

public function getRouteKeyName()
{
	return 'slug';
}
2 likes
Userinfo's avatar

@johnDoe220 Thank you :) , have a special error, when I put

public function getRouteKeyName ()
    {
        return 'slug';
    }

I still get a 404 error and when I remove the function my id takes over and it works perfectly with the id in the route, I saw someone on laracasts used this:

 public function getRouteKeyName ()
    {
        return '[slug]';
    }

And that causes me an error, I think that if I get an error while putting the hooks, my slug is well taken into account however. Regarding my factories I did this is this correct according to you?

 Schema :: create ('post', function (Blueprint $ table) {
            $ table-> id ();
            $ table-> string ('name');
            $ table-> text ('description');
            $ table-> string ('slug') -> unique ();
            $ table-> string ('picture');
            $ table-> timestamps ();
            // Foreign key 1
            $ table-> unsignedBigInteger ('user_id');
            $ table-> foreign ('user_id') -> references ('id') -> on ('users');
        });

Thank you

johnDoe220's avatar

@Userinfo that's right, If you want to know more about Laravel, I have written a personal website script. To receive it, send a message to my telegram so that I can send it to you. Good luck.

Telegram ID : ciscocontact
1 like

Please or to participate in this conversation.