Laravel : Handle findOrFail( ) on Fail

2020-06-16 01:33发布

I am looking for something which can be like findOrDo(). Like do this when data not found. Something could be like

Model::findOrDo($id,function(){
   return "Data not found";
});

Is there any similar thing in laravel that I can do this elegantly and beautifully ?

*I tried googling but could not find one

6条回答
2楼-- · 2020-06-16 01:53
use Illuminate\Database\Eloquent\ModelNotFoundException;

// Will return a ModelNotFoundException if no user with that id
try
{
    $user = User::findOrFail($id);
}
// catch(Exception $e) catch any exception
catch(ModelNotFoundException $e)
{
    dd(get_class_methods($e)); // lists all available methods for exception object
    dd($e);
}
查看更多
来,给爷笑一个
3楼-- · 2020-06-16 02:11

A little later for the party, from laravel 5.4 onward, Eloquent Builder supports macros. So, I would write a macro (in a separate provider) like follows.

Builder::macro('firstOrElse', function($callback) {
   $res = $this->get();

   if($res->isEmpty()) {
       $callback->call($this);
   }

   return $res->first();
});

I can then do a retrieval as follows.

$firstMatchingStudent = DB::table('students')->where('name', $name)
    ->firstOrElse(function() use ($name) {
        throw new ModelNotFoundException("No student was found by the name $name");
    });

This will assign the first object of the result set if it is not empty, otherwise will adapt the behaviour I pass into the macro as a closure (throw Illuminate\Database\Eloquent\ModelNotFoundException in this case).

For the case of a model also this would work, except that models always return the builder instance.

查看更多
够拽才男人
4楼-- · 2020-06-16 02:12

By default, when you use an Eloquent model’s findOrFail in a Laravel 5 application and it fails, it returns the following error:

ModelNotFoundException in Builder.php line 129:
'No query results for model [App\Model]'.

So to catch the exception and display a custom 404 page with your error message like "Ooops"....

Open up the app/Exceptions/Handler.php file, and add the code shown below to the top of the render function:

public function render($request, Exception $e)
{
   if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) 
   {
      abort(404, 'Oops...Not found!');
   }

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

Source: https://selftaughtcoders.com/from-idea-to-launch/lesson-16/laravel-5-findorfail-modelnotfoundexception-show-404-error-page/

查看更多
再贱就再见
5楼-- · 2020-06-16 02:15

Another option is to modify the default Laravel Exception Handler, found in app/Exceptions/Handler.php on the render() function I made this change:

public function render($request, Exception $e)
{
    if(get_class($e) == "Illuminate\Database\Eloquent\ModelNotFoundException") {
        return (new Response('Model not found', 400));
    }
    return parent::render($request, $e);
}

That way instead of getting a 500, I send back a 400 with a custom message without having to do a try catch on every single findOrFail()

查看更多
等我变得足够好
6楼-- · 2020-06-16 02:20

An alternative process could be to evaluate a collection instead. So,

$modelCollection = Model::where('id', $id)->get();
if(!$modelCollection->isEmpty()) {
    doActions();
}

I agree it isn't as elegant, a one-liner or as case specific as you or I might like, but aside from writing a try catch statement every time, it's a nice alternative.

查看更多
劳资没心,怎么记你
7楼-- · 2020-06-16 02:20

as of Laravel v5.7, you can do this (the retrieving single model variation of @thewizardguy answer)

// $model will be null if not found
$model = Model::where('id', $id)->first();

if($model) {
    doActions();
}
查看更多
登录 后发表回答