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

curtiplas's avatar

Handling no results on Controller@show method

So I thought I'd make this a different title name since there are so many as it relates to the "error" message: No query results for model [App\WaitList].

What I'd really like to know, is not WHAT that message means, but how to handle it better.

Essentially I want to be able to pass an id to the show controller then either return a view displaying the related model's info, OR return a view stating that the model doesn't exist (in this case a user/waitlister) then offer the option to join the waitlist.

Here is my current routes/web.php

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

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

Auth::routes();

Route::get('/waitlist/join', 'WaitListController@create');
Route::resource('waitlist', 'WaitListController', [
    'only' => 
        ['show', 'store', 'destroy']
    ]);

Here is my current WaitListController

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\WaitList;
use App\Http\Requests\WaitlistRequest;
use App\Mail\WaitListWelcome;

class WaitListController extends Controller
{
    public function create()
    {
        return view('waitlist.create');
    }

    public function store(WaitListRequest $request)
    {
        //store in DB
        $waitlist = WaitList::create(
            request(['name', 'email'])
        );

        Mail::to($waitlist)->send(new WaitListWelcome($waitlist));

        session()->flash('message', 'Thanks for joining the wait list!');

        return redirect('/');
        //redirect
        
    }
    public function show(WaitList $waitlist){

        return view('waitlist.show', compact('waitlist'));
    }
}

As one would expect this works fine when a row exists in the waitlist table that matches the id I pass, but when it doesn't I get the standard laravel message telling me:

(2/2) NotFoundHttpException No query results for model [App\WaitList].

from playing with die & dumps it looks like this is thrown before anything inside the control method executes.

Any ideas on how I can handle this?

0 likes
11 replies
tisuchi's avatar
tisuchi
Best Answer
Level 70

Normally show($id) method use for displaying data from database based on a specific ID. Imagine that, you have a post id 33 that you want to show. So, what you have to do-

public function show($id)
{
    return view('showarticle', ['article' => Article::findOrFail($id)]);
}

Ref: https://laravel.com/docs/5.1/controllers#basic-controllers

For you case, you need to pass a id as a parameter of your method.

public function show($id){
    return view('waitlist.show', ['waitlist' => Waitlist::findOrFail($id)]);
}
2 likes
Norris's avatar
public function show($id)
{
    $waitList = WaitList::find($id);
    if(!$waitList)
    {
        return view('waitlist.show',compact('waitlist'))->with('error','WaitList not found');
    }
    return view('waitlist.show', compact('waitlist'));

}

So you can check for {{session('errors') }} in your blade file to handle the error

OR

public function show($id)
{
    return view('waitlist.show')->with(['waitlist'=>WaitList::find($id)]);

}

so you can display the appropriate message if waitlist is empty

in your view

@if(!$waitlist)

// Handle empty results here

@else

// Display results

@endif
1 like
curtiplas's avatar

@tisuchi @Norris sorry forgot to mention that I'm using a getKeyRoute to pass the email address in the url.

Also If I understand correctly the best method to handle this would be to pass the ID and run the query inside the show method instead of type hinting in the show method?

tisuchi's avatar

Yes. You are right.

By the way, if you use get post method, you just need to add a more line of code-

public function show(Request $request){
    
    //example.com/route/?id=397127
    $id = $request->query('id');

    return view('waitlist.show', ['waitlist' => Waitlist::findOrFail($id)]);
}

Make sure you have imported request top of your class.

use Illuminate\Http\Request;
2 likes
Jaytee's avatar

@tisuchi Little tip for you :)

You can actually just use the request to get query parameters, as you would in a post request.

request('id');
$request->id;
sutherland's avatar

You can set up a custom view for your 404 pages in resources/views/errors/404.blade.php. This would have the benefit of being able to show your waiting list form on any page that doesn't exist.

You might also want to use the Exception handler to customize what happens when a model isn't found. Using a method on your model like findOrFail() or firstOrFail() will throw a ModelNotFoundException that you can catch in app/Exceptions/Handler.php.

public function render($request, Exception $exception)
{
    if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
        return response()->view('waitlist.join', [], 404);
    }

    return parent::render($request, $exception);
}
tisuchi's avatar

@Jaytee

TQVM. I agreed with you. You know what, its a same things. Its a dynamic way to access global scope.

Snapey's avatar

Because you use Route model binding, the error is thrown before your code.

Your options are to disable this and look up the model in your controller or catch the error in kernel.php

Thinking about it, it would not surprise me if Taylor had already thought about this and handled it by allowing you to make the model optional

Give this a go?

public function show(WaitList $waitlist=null){
curtiplas's avatar

Thank you everyone for the responses!

@sutherland using a 404 won't work for me as I don't want to return a 404 for this page; where I would want to return a 404 on other non-existent pages.

@Snapey I tried the snippet you posted in my WaitListController, but the results are the same. I'm not entirely sure what it's doing to be honest.

This is what I tried:

    public function show(WaitList $waitlist=null){

        return view('waitlist.show', compact('waitlist'));
    }

I might try the Exception handler method that @sutherland posted, if that doesn't work or proves to difficult I'll probably just get rid of the Route model binding and lookup the inside the show method.

curtiplas's avatar

I ended up doing this in my controller

    public function show($email){
            return view('waitlist.show',['waitlist' => WaitList::where(compact('email'))->first()]);
        }

then just running an if($waitlist) on my blade to display one visual or another.

Thank you all!

Snapey's avatar

Looks like a way to do it is to customise the route model binding

RouteServiceProvider

public function boot()
{
    parent::boot();

    Route::bind('waitlist', function ($value) {
        return App\Waitlist::find($value);
    });
}

and then the controller should receive an instance of Waitlist, or null - and not throw a 404

Please or to participate in this conversation.