Dark Cyber
Dark Cyber

Reputation: 2231

Laravel 5 : How to use findOrFail() method?

I just follow some tutorial and so far what I do is :

my App/Exceptions/Handler.php

<?php
...
use Illuminate\Database\Eloquent\ModelNotFoundException;
...
public function render($request, Exception $e)
{
    if ($e instanceof ModelNotFoundException){
        abort(404);
    }
        return parent::render($request, $e);
}

and my UsersController looks like this :

...
public function edit($id)
{
    $data = User::findOrFail($id);
    $roles = Role::where('title', '!=', 'Super Admin')->get();
    return View('admin.user.edit', compact(['data', 'roles']));
}
...

with the above code if I visit http://my.url/users/10/edit I get NotFoundHttpException in Application.php line 901:, yes because there is no id 10 in my record, but with User::find($id); I get normal view without data, since no id 10 in my record.

What I want is show default 404 then redirect to somewhere or return something if record not found with User::findOrFail($id); ? How I can do that ?

Thanks, any help appreciated.

ps: .env APP_DEBUG = true

Upvotes: 8

Views: 94110

Answers (4)

Iklan Hits
Iklan Hits

Reputation: 101

public function singleUser($id)
{
    try {
        $user= User::FindOrFail($id);
        return response()->json(['user'=>user], 200);
    } catch (\Exception $e) {
        return response()->json(['message'=>'user not found!'], 404);
    }
}

Upvotes: 10

Edwin Krause
Edwin Krause

Reputation: 1806

Late addition to above topic: If you want to handle the exception for an API backend and you don't want to make the check for an empty result in each method and return a 400 Bad request error individually like this...

public function open($ingredient_id){
    $ingredient = Ingredient::find($ingredient_id);
    if(!$ingredient){
        return response()->json(['error' => 1, 'message' => 'Unable to find Ingredient with ID '. $ingredient_id], 400);
    }
    return $ingredient;
}

Instead use findOrFailand catch exception in app/Exceptions/Handler.php.

public function render($request, Exception $exception)
{
    if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
        return response()->json(['error'=>1,'message'=> 'ModelNotFoundException handled for API' ], 400);
    }
    return parent::render($request, $exception);
}

This will then look like this in your Controllers:

public function open($ingredient_id){
    return Ingredient::findOrFail($ingredient_id);
}  

which is much cleaner. Consider that you have plenty of Models and plenty of Controllers.

Upvotes: 2

Amitesh Bharti
Amitesh Bharti

Reputation: 15713

findOrFail() is alike of find() function with one extra ability - to throws the Not Found Exceptions

Sometimes you may wish to throw an exception if a model is not found. This is particularly useful in routes or controllers. The findOrFail and firstOrFail methods will retrieve the first result of the query; however, if no result is found, a Illuminate\Database\Eloquent\ModelNotFoundException will be thrown:

$model = App\Flight::findOrFail(1);

$model = App\Flight::where('legs', '>', 100)->firstOrFail();

If the exception is not caught, a 404 HTTP response is automatically sent back to the user. It is not necessary to write explicit checks to return 404 responses when using these methods:

Route::get('/api/flights/{id}', function ($id) {
    return App\Flight::findOrFail($id);
});

Its not recommended but If still you want to handle this exception globally, following are the changes as per your handle.php

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $exception
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $exception)
{
    if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {

        //redirect to errors.custom view page 
        return response()->view('errors.custom', [], 404);
    }

    return parent::render($request, $exception);
}

Upvotes: 6

bernie
bernie

Reputation: 10390

This does what you asked. No need for exceptions.

public function edit($id)
{
    $data = User::find($id);
    if ($data == null) {
        // User not found, show 404 or whatever you want to do
        // example:
        return View('admin.user.notFound', [], 404);
    } else {
        $roles = Role::where('title', '!=', 'Super Admin')->get();
        return View('admin.user.edit', compact(['data', 'roles']));
    }
}

Your exception handler is not necessary as it is. Regarding Illuminate\Database\Eloquent\ModelNotFoundException:

If the exception is not caught, a 404 HTTP response is automatically sent back to the user, so it is not necessary to write explicit checks to return 404 responses when using [findOrFail()].

Also, I'm pretty sure you get the exception page instead of 404 now because you're in debug mode.

Upvotes: 26

Related Questions