Laravel 5.5 - Handle Error Exception for 'where' - laravel

In Laravel 5.5 I am trying to handle an error exception like this...
try {
$fruits = Fruit::where('fruit_id', $user->fruit->id)->get();
}
catch(ModelNotFoundException $e) {
return Response::json(array(
'error' => true,
'status_code' => 400,
'response' => 'fruit_id not found',
));
}
But this is giving me a 'Trying to get propert of non-object' error
The same error handling works correctly for findorfail, how should I be doing this for the 'where' statement?

I think you are passing wrong values in your where query in the try block.
try {
$fruits = Fruit::where('fruit_id', $user->fruit->id)->get();
}
Is it fruit_id or just id because you are querying it on fruit model itself.

Thanks to some pointers in the comments I changed to
try {
$fruits = Fruit::where('fruit_id', $user->fruit->id)->get();
}
catch(\Exception $e) {
return Response::json(array(
'error' => true,
'status_code' => 400,
'response' => 'fruit_id not found',
));
}
All is now working now I am catching the correct exception

Tested on Laravel 5.7
try {
$fruits = Fruit::where('fruit_id', $user->fruit->id)->get();
}
catch(\Exception $e) {
abort(404);
}

Even though you got it working, I'd like to make mention of Laravel's Exception Handler.
The report method allows you to catch any exception type and customize how you wish to process and move forward. There is a report helper function as well which is globally accessible.
Furthermore, reportable and renderable exceptions allow you to create and customize your responses.

Try the below code:
if ($user->fruit) {
try {
$fruits = Fruit::where('fruit_id', $user->fruit->id)->get();
} catch(\Exception $e) {
return Response::json(array(
'error' => true,
'status_code' => 400,
'response' => 'fruit_id not found',
));
}
} else {
return "User Fruit doesn't exists!!";
}

Related

Changing default error message when record not found - Laravel API

I am building a simple API, which there is a point that when the ID entered in the endpoint URL does not point to a valid record, I get a standard NotFoundHttpException. And I cannot figure out how to override this in order to provide my own error message response as I do not wish to share my Model name etc.
Endpoint
Route::get('{mrl}', [MrlController::class, 'show']);
Controller
public function show(Mrl $mrl)
{
if ($data = $mrl) {
return response(['status' => 'ok', 'data' => $data], 200);
} else {
return response(['status' => 'error', 'message' => 'Could not retrieve data'], 500);
}
}
When I run this when a record exists I receive the following which is what I expect.
{
"status": "ok",
"data": {
"id": 98,
"market_id": 1,
"crop_id": 2,
"chemical_id": 113,
"maximum_residue_level": null,
"exempt": 0,
"comments": null,
"date_verified": "2021-10-07",
"created_at": "2021-10-19T05:42:12.000000Z",
"updated_at": "2021-10-19T05:42:12.000000Z"
}
}
However, when I enter an ID in the route endpoint for a record that does not exist, I receive the following:
{
"message": "No query results for model [App\\Seasonal\\Mrl] 99"
}
This is happening from what I understand to be the auto find of the record between the Route and the controller, and I am lost as to how to customize this behavior.
Thanks in advance for your help!
you don't show the code where you are fetchning the model from the database but we can assume something like that:
$mrl = Mrl::findOrFail($id);
show($mrl);
The model findOrFail() method throws an exception when the model is not found, which is convenient when you want to adapt the response.
You can imagine something like that:
try {
$mrl = Mrl::findOrFail($id);
return response(['status' => 'ok', 'data' => $data], 200);
} catch (ModelNotFoundException $e) {
return response(['status' => 'error', 'message' => 'Could not retrieve data'], 500);
}
The idea is to catch the error thrown by your model to change the message and status code of the response.
When building APIs you should event add a "generic" catch statement for any unhandled errors to display a standardized generic error message and log what happened, like this:
try {
$mrl = Mrl::findOrFail($id);
// Do more things that could generate errors ?
return response(['status' => 'ok', 'data' => $data], 200);
} catch (ModelNotFoundException $e) {
// Not found
return response(['status' => 'error', 'message' => 'Could not retrieve data'], 500);
} catch (\Exception $e) {
// Generic error
\Log::error($e);
return response(['status' => 'error', 'message' => 'An error occured'], 500);
}
After spending time reading the docs I finally found the answer on how to customize the behaviour if a record is found when utilising Eloquents Route Model Binding.
In the Laravel docs, there is a method for this explicit purpose, to override the default behaviour when the bound model does not have a valid record.
The method for doing this is to chain the ->missing() function call to the end of your route and then providing the behaviour for the response you wish to provide. As below:
Route::get('{mrl}', [MrlController::class, 'show'])->missing(function () {
return response(['status' => 'error', 'message' => 'Invalid query.'], 404);
});
Chaining this method onto my request has enabled me to return the generic response I was hoping for when querying an invalid model record.

Try Catch incorrect for value null in laravel

I am making a selection for api but when you do not have the contract informed you are returning an empty array [] but you should return contract not found.
I believe that the catch is in the wrong way, but I already did some other tests and it didn't work.
try {
if(empty($contratos)){
return response()->json(
$contratos,
200
);
}else{
return response()->json([
"message" => "Contract not found",
"code" => "CONTRACT_NOT_FOUND"
], 406
);
}
} catch (\Exception $e) {
if ($exception->getStatusCode() == 406){
return response()->json([
"message" => "Contrato não encontrado",
"code" => "CONTRACT_NOT_FOUND"
]);
}
}
You can check if there are no results from the query like this.
if ($contratos->isEmpty()) {
return response()->json([
"message" => "Contract not found",
"code" => "CONTRACT_NOT_FOUND"
], 406);
} else {
return response()->json($contratos, 200);
}
you should put a dd($exceptopm->getStatusCode()) in the exception block and see what is the status code returned, typically not found should be 404 instead of 406
you should also try to use a switch statement
switch($exception->getStatusCode()) {
case 400:
return [];
break;
case 404:
return [];
break;
default:
return [];
}

Laravel - How to make the application show the specific error to the user

I have Laravel-5.8 project code:
public function store(StoreTypeRequest $request)
{
$userCompany = Auth::user()->company_id;
DB::beginTransaction();
try{
$data = Type::create([
'name' => $request->name,
'parent_id' => $request->parent_id,
'max_score' => $request->max_score,
'comment' => $request->comment,
]);
$data1 = DB::table('types')->select('max_score')->where('id', $request->parent_id)->where('company_id', $userCompany)->whereNull('parent_id')->first();
$data->update(['max_score1' => $data1->max_score]);
DB::commit();
Session::flash('success', 'Type is created successfully');
return redirect()->route('types.index');
} catch (Exception $exception)
{
DB::rollback();
Session::flash('error', 'Action failed! Please try again');
return back();
}
}
When I submitted, I got this error:
Action failed! Please try again
How do I make the application to show specific error, so that the user will be clear about what caused the error?
Thank you
Catch an exception on using try-catch statements :
Use Exception;
try
{
// write your codes here
}
catch(Exception $exception)
{
dd($exception->getMessage());
}
If you want to catch PDO Exception :
use PDOException;
try
{
//write your codes here
}
catch(PDOException $e)
{
dd($e->getMessage());
}
If above code isn't working then give a backslash \ before Exception & PDOException

Creating Password Reset Function without using Laravel make:auth

I'm dealing with Laravel 5.6. I am using JWT Authentication, and I create my own authentication controller.
This is my recover method at AuthController,
public function recover(Request $request)
{
$user = User::where('email', $request->email)->first();
if (!$user) {
$error_message = "Your email address was not found.";
return response()->json(['success' => false, 'error' => ['email'=> $error_message]], 401);
}
try {
Password::sendResetLink($request->only('email'), function (Message $message) {
$message->subject('Your Password Reset Link');
});
} catch (\Exception $e) {
$error_message = $e->getMessage();
return response()->json(['success' => false, 'error' => $error_message], 401);
}
return response()->json([
'success' => true, 'data'=> ['message'=> 'A reset email has been sent! Please check your email.']
]);
}
In postman, if I execute the recover method, I get this message
{
"success": false,
"error": "Route [password.reset] not defined."
}
How can I deal with this. thanks!
You need to give the route a name, in this case password.reset. In your routes.php (or wherever you've defined them) call the name method:
Route::post('/password/reset', 'AuthController#recover')->name('password.reset');
If you haven't run make:auth you don't have the route defined, as the error itself is saying.
Try to define the following route in routes/web.php
Route::post('/pwdreset', 'AuthController#recover')
->name('password.reset');

How do I handle route exception not defined?

I created dynamic sidebar menu and when I try to insert new menu I am getting error message Route [nameroute] is not defined. How do I handle this error with try catch ?
This is my controller file.
DB::beginTransaction();
try
{
$insert = AppMenu::insertGetId([
'description' => $request->description,
'menu_url' => $request->menu_url ? $request->menu_url:null,
'menu_alias' => $request->menu_alias ? $request->menu_alias:null,
'ismenu' => $request->ismenu,
'parent' => $request->parent ? $request->parent:null,
'menu_icon' => $request->menu_icon,
'menu_order' => $request->menu_order
]);
DB::table('appmenu_role')->insert([
'appmenu_id' => $insert,
'role_id' => $role
]);
}
catch (\InvalidArgumentException $e)
{
return Redirect::back()->with('infoMessage', "Route not defined. ");
}
DB::commit();
Session::flash('successMessage', 'Menu Created');
return Redirect('menu');
You should use Exception class to catch any kind of exception.
catch (\Exception $e)
{
return Redirect::back()->with('infoMessage', "Route not defined.");
}

Resources