Laravel $e->getMessage empty on Request validation error - php

I'm trying to setup custom error handlers in Handler.php but when I try to get the error message when a Request validation isn't met I get an empty response.
public function render($request, Exception $e)
{
dd($e->getMessage());
return parent::render($request, $e);
}
My rules are set to:
'min:10'
So when I don't provide parameters of length 10 I want it to output that error within $e->getMessage() so I can do whatever I want to do with it, but the error is always empty. What am i doing wrong?

Exception will not give you errors that occurs for Validator.
Validator error are sent on its object and by errors() method. So, after calling the errors method on a Validator instance, you will receive an Illuminate\Support\MessageBag instance, which has a variety of convenient methods for working with error messages.
For more details: https://laravel.com/docs/5.2/validation#custom-error-messages

Related

Laravel try / catch on not working

I've searched a few questions for a reason my code is not throwing an error correctly, but I can't figure it out.
I have the following function in my controller
<?php
public function suspend($id)
{
try {
$this->collection = $this->class::find($id);
$this->collection->delete();
return $this->respond_with_success();
} catch (\Exception $e) {
return $this->respond_with_error('Failed to suspend resource with id: ' . $id);
}
}
For reference, I'm using soft deletes. I can suspend a resource once no problem. If I try to suspend one that's already suspended, Laravel correctly throws a 500 as I can see in the log file /storage/logs/laravel.log
This is part of the error I see;
local.ERROR: Call to a member function delete() on null....
Without using
withTrashed() in the query, a row quite obviously cannot be found. So this makes sense.
Great...so why does my catch not actually catch anything? I see a 500 error in the browser, but my application should allow me to continue and handle that error correctly. But it just falls over completely...
The respond_with_error function is below. I've tried changing the $code to 200 in testing, but this doesn't change anything. I've tested returning a simple string rather than with this function to no avail, so I don't think there's anything wrong with this part.
<?php
protected function respond_with_error($message = 'error', $code = 500)
{
return Response::json([
'success' => false,
'message' => $message,
], $code);
}
I'm running Laravel 5.6.29
There are two ways to address this. The first thing to note is ERROR: Call to a member function delete() on null is not an exception, it is a fatal error.
You can use findOrFail instead of find to throw an Exception when the model is not found and that will work.
You could also catch Throwable instead of Exception to catch errors and exceptions (as of PHP7) or just Error to catch errors.
As the Error hierarchy does not inherit from Exception, code that uses catch (Exception $e) { ... } blocks to handle uncaught exceptions in PHP 5 will find that these Errors are not caught by these blocks. Either a catch (Error $e) { ... } block or a set_exception_handler() handler is required.
Read more on PHP7 Error Handling here: http://php.net/manual/en/language.errors.php7.php

Laravel - One view for all possible errors

So I want to cover all posible and unexpected errors (like 401, 404, 500) with just one view. I want the same view to show up on all possible errors. I came up with a solution - to copy/paste the same code and just name the views with different error codes. But that seems stiff and wrong. Is there a better way of achieving this?
In the file app/Exceptions/Handler.php you can change what happens when an exception is thrown. In particular there's a render method in there that you can use to catch all the exceptions in an application.
public function render($request, Exception $e)
{
// Handle your error here. Perhaps you can show a view
// when a condition is met. Anything that isn't caught
// here will be handled by Laravel with the
// parent::render call below
return parent::render($request, $e);
}
The parent::render($request, $e) is where Laravel would normally show it's exception/oops page. So by overriding this method you can catch all application errors, including 404, 401 etc.
A cleaner way to achieve this effect is by modifying Laravel's exception handler.
Modify App\Exceptions\Handler to catch every error and return your shared custom error page.
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $e
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $e)
{
if ($e instanceof NotFoundHttpException) {
return response()->view('errors.custom', [], 404);
}
return parent::render($request, $e);
}
Some customization may be required to fully meet exactly what & how you want data passed to your shared custom view.
Pass the error code to your view on the handler, and display the code on your page, use a switch to handle all the messages depending on the error code.
You can create one unique view (default to 404 error), use try catch in your code to capture other errors and call to this view with parameters so you can change the 404 default error to other error.

Implementation of Exception Handling in Laravel 5.2

I am trying to implement exception handling in my application. For this Laravel framework has its own mechanism to handle the exception using report and render method. But to implement exception I need to track the source from where the exception has been raised e.g. specific page, route etc. For this I need to pass the url to report and render method but unable to do so. What needs to be done in order to implement this in below report and render function.
public function report(Exception $e)
{
parent::report($e);
}
public function render($request, Exception $e)
{
/* Token mismatch Exception handler start */
if ($e instanceof \Illuminate\Session\TokenMismatchException) {
return response()->view('errors.sessionExpire', [], 500);
}
/* Token mismatch Exception handler start */
return parent::render($request, $e);
}
As you can see from your own example, you have an instance of Request in the argument list. And Request has all request-specific details like current route, URL and so on.
$request->url(); // Current request URL
$request->fullUrl(); // With query parameters
$request->route(); // Get the route closure for this request path
You can also create your own exception classes that accept as many parameters as you wish!
And the less comfortable way already mentioned – you could go through the exception trace.
You need to use Exception::getTrace
var_dump($e->getTrace());
above line will give you all details regarding exception.
public function report(Exception $e){
echo '<pre>'; // add this line
print_r($e->getTrace()); // add this line
parent::report($e);
}

Unable to use ApiProblemListner in apigility using zf2

I am new in zendframework. I am using apigility for rest services and ApiProblemListner to return the response if any error occures.
I have one function in model and this function just through an exception using php exception to use in catch block
I am using model function as the utility function in controller to catch those Exception. While catching exception I am using as
try{
imageUploade(); // this function in model and throwing exception if any error
}catch(\Exception $e){
return new ApiProblemResponse(new ApiProblem(500 , $e->getMessage()));
}
if imageUploade() throw an exception if the image size is more then I am able to catch the exception in catch block. I tried echo $e->getMessage(); and its printing the exception bt if I use new ApiProblem(500 , $e->getMessage()) it is not retuning the json error response with the 500 message. It is returning nothing. even it is not showing any error.
Seems like it is unable to render the error with this class. I am not sure if any event needs to add.
I have tried to search for documents but unable to find it.
Thanks in advance.
Normally it should work if you return an ApiProblemResponse straight from a controller action.
Are you sure your Api-Problem module is active?
Try once like this:
<?php
Application\Namespace;
use ZF\ApiProblem\ApiProblem;
use ZF\ApiProblem\ApiProblemResponse;
class IndexController
{
/**
* #return ApiProblemResponse
*/
public function indexAction()
{
return new ApiProblemResponse(new ApiProblem(500, 'test'));
}
}
If that doesn't work then I think your Api-Problem module is not running or the exception is never caught.

Laravel catch exception and add message to a messagebag

I have a repository that throws an exception if it can't find a record in the database. Rather than redirect to another page I just want to display a warning alert as the record is not critical to the page but is an "exceptional event".
It's probably best to demonstrate with code:
// FxRateRepositoy
public function getRate(/** args **/)
{
$rate = FxRate::where(.... //query to get the rate
if (!rate)
throw new NonExistentCurrencyException(//message);
return $rate;
}
In my start/global.php I have a handler:
App::error(function(NonExistentCurrencyException $e)
{
Session::flash('alert', $e->getMessage());
return \\ ??
});
What to return? I must return a response or the exception continue uncaught. I want to continue to the intended page but with the alert flashed in the session. Is this possible without having to use try catch blocks in every place this method is called?
Ass an additional question, assuming this exception may be thrown multiple times in one request, what's the best way to accumulate alert messages and display them? I'm thinking something akin to the validation messageBag. Can I just use the global $errors variable or should I create a new, specific messagebag for this purpose?
The problem is that if you return nothing from App::error Laravel will display it's default error page. On the other side you can't return a response because you don't know what response it should be in the error handler.
I suggest you handle it in the controller itself.
You can catch the exception there and flash the message or don't throw an exception at all:
$rate = FxRate::where(.... //query to get the rate
if (!rate){
Session::flash('alert', 'Whoops');
}
Also the findOrFail() and firstOrFail methods might be of use. They throw an ModelNotFoundException if the query yields no results:
try {
$rate = FxRate::where(....)->firstOrFail()
// and so on
} catch (Illuminate\Database\Eloquent\ModelNotFoundException $e){
Session::flash('alert', 'Whoops');
}
As for a messages system, take a look at the laracasts/flash package

Categories