Laravel throw ValidationException but not hitting destroy method's catch block? - php

I am trying to return a custom exception message using Laravel's ValidationException class. I have it successfully working in the following example:
public function store(Request $request)
{
$this->validate($request, CurrencyValidatorArrays::$store);
try {
$this->currenciesInstance->createOrUpdateCurrency($request->all());
return redirect()->route('currencies.index')
->with('success', 'Successfully created currency');
} catch (Exception $e) {
return redirect()->route('currencies.create')
->with('error', $e->getMessage());
}
}
where the exception is thrown from within createOrUpdateCurrency()
if(Currency::where('position', $data['position'])->where('id', '!=', $id)->exists()) {
throw ValidationException::withMessages([
'error' => ['Position value is already taken']
]);
}
This then passes the exception message back to my view for display.
However, I am trying to implement this somewhere else when trying to delete a company I am checking that no users exist first:
public function destroy($id)
{
try {
$this->companiesInstance->deleteCompany($id);
return redirect()->route('companies.index')
->with('success', 'Successfully deleted company');
} catch (Exception $e) {
return redirect()->route('companies.index')
->with('error', $e->getMessage());
}
}
Inside of deleteCompany():
$company = Company::find($id);
if($company->users()->exists()){
throw ValidationException::withMessages([
'error' => ['Position value is already taken']
]);
}
For some reason this doesn't hit my catch block from the main destroy method,if I change the exception type to ValidationException from Exception I can access and see the exception object but not in the way I can in the Store() methods version. Any ideas what is going on here?
UPDATE:
So I have a some what of a workaround:
To get by the exception type issue I used:
catch (ValidationException | Exception $e) { ...
But that still does not help when accessing the exception messages as when it's of type ValidationException the default constructor validation message is returned from getMessage() and not my specified one.

PHP 7 handles exceptions a bit differently. You can read it here.
Coming back to your code, you have to try and catch object of Throwable instead of Exception.
try
{
// Code that may throw an Exception or Error.
}
catch (Throwable $t)
{
// Code that handles the error
}
Hope this helps.

Related

Catch errors with Laravel API Resource

I'm trying to use Laravel API Resource and handle the error message by sending a specific HTTP code
Here is my code :
public function show($id)
{
try {
return FruitResource::make(Fruit::find($id));
}
catch(Exception $e)
{
throw new HttpException(500, 'My custom error message');
}
}
My try/catch is systematically ignored when I try to access the route.
I am voluntarily accessing an object that is not in the database. I have ErrorException with message Trying to get property 'id' of non-object.
I would like to be able to send my own Exception here, in case the user tries to access data that doesn't exist. And return a json error.
Try this (notice the \ before Exception):
public function show($id)
{
try {
return FruitResource::make(Fruit::find($id));
}
catch(\Exception $e)
{
throw new HttpException(500, 'My custom error message');
}
}

Try/catch doesn't catch an exception in Yii2

as the title says, try/catch doesn't catch throwed exception.
Here is my code:
public function edit($id)
{
try {
$this->permissions($id);
return $this->redirect(['edit/list']);
} catch (Exception $e) {
Yii::$app->session->setFlash('error', Yii::t('app', 'PERMISSIONS_NOT_FOUND'));
}
}
I'm trying to catch an exception which is in permissions() method. Permissions method is:
private function persimssions($id)
{
$permitted = false;
if (!$permitted) {
throw new ForbiddenHttpException(Yii::t('app', 'MODULE_NO_PERMISSIONS'));
}
}
Could someone explain me what is wrong? Thanks for any help
I almost sure that your Exception is in fact yii\db\Exception - check this in use statements. If so it's obvious that it will not catch ForbiddenHttpException.
If you want to catch all exceptions write \Exception in catch or add proper use statement.

Prevent laravel message to be displayed and redirect the user to custom page issue in Laravel 5

I would like to catch somehow the laravel error, warning message. I don't want to disable them from the config/app.php file. I am using monolog to log some information.
This is my piece of code:
public function view($id){
try {
$tag = Tags::find(12313); // tags is a model
}catch(Exception $error){
echo 'error'; exit();
$this->log->logMessage(Logger::ERROR, $error->getMessage());
return redirect()->route('admin.tags')->with(['msg' => 'Smth went wrong']);
}
}
$this->log is a class where I am using the monolog class to log information.
The fact is that right now , it doesn't go to the catch part . I don't get the error message. I'm getting this message from laravel:
Trying to get property of non-object (View: ......
I intentionally put the number 12313 there to see if it is working or not. And for some reason is not working and I am not redirected . The idea, if something happened I want to redirect the user to a specific page with a general error message. How can I achieve that ?
You can do it in laravel .You can handle erors in App\Exceptions\Handler class
public function render($request, Exception $exception)
{
if($exception instanceof NotFoundHttpException)
{
return response()->view('errors.404', [], 404);
}
if ($exception instanceof MethodNotAllowedHttpException)
{
return response()->view('errors.405', [], 405);
}
if($exception instanceof MethodNotAllowedHttpException)
{
return response()->view('errors.404', [], 405);
}
return parent::render($request, $exception);
}
find() method doesn't throw an exception if the record is not found. So do this instead:
public function view($id)
{
$tag = Tags::find(12313); // tags is a model
if (is_null($tag)) {
$this->log->logMessage(Logger::ERROR, $error->getMessage());
return redirect()->route('admin.tags')->with(['msg' => 'Smth went wrong']);
}
}
Or use findOrFail() which will throw an exception if specified record is not found.
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

Set http code for Symfony constraint validation failure

Shortly: how can you set a specific http error code, instead of a generic 500, when a constraint fails on entity save?
Details
I'm using Symfony custom constraint #UniqueEntity (http://symfony.com/doc/current/reference/constraints/UniqueEntity.html) to assert that some data is not duplicated when saving an entity.
If this constraint check results in a violation, I get a 500 http code, while others may be more appropriate, e.g. 409 - Conflict (https://httpstatuses.com/409).
I can't seem to find any documentation on how to override the validation response.
Thank you in advance for any suggestion.
Maybe you could create a Listener to the event : kernel.exception
And then you will have something like :
<?php
public function onKernelException(GetResponseForExceptionEvent $event)
{
$e = $event->getException();
if ($e instanceof NameOfTheException) {
// logic here
return (new Response())
->setStatusCode(409)
;
}
}
Just catch exception in controller:
public function saveAction()
{
try {
$entity = new Entity('duplicate name');
$this->entityManager->persist($entity);
$this->entityManager->flush();
return new Response();
} catch(UniqueConstraintViolationException $e) {
return new Response('Entity with same name already exists', Response::HTTP_CONFLICT);
} catch (\Exception $e) {
return new Response('Internal error', Response::HTTP_INTERNAL_SERVER_ERROR);
}
}

Laravel 5 - try catch exception not working

I am new to laravel5 and this code fails to catch all the exceptions.
I don't know what's wrong, please help.
public function delete($id)
{
$sql = $this->deleteSql();
DB::beginTransaction();
try {
$deleteData = Db::delete($sql, ['id' => $id]);
if (!$deleteData) {
return false;
}
return true;
} catch (\Exception $e) {
DB::rollback();
return $e->getMessage();
}
DB::commit();
}
It will give me :
Illuminate\Database\QueryException: SQLSTATE[22P02]:
and
Caused by
PDOException: SQLSTATE[22P02]:
Your method is not going to catch block at all since it is returning bool from try block.
Also I don't know what made you use try...catch block.
I more error:
Db::delete($sql, ['id' => $id]);
If you have defined Db, then it is okay. But if not, then it will throw error.
Also there is no need to use transactions, unless you are testing your application with any PHP Testing tool like phpUnit / phpSpec, etc.
Solution:
There is no need to use try..catch block at all.
Just call the delete method on the model that you wish to delete, and you will be done, like so:
public function delete($id)
{
YourModel::delete($id); // Replace YourModel with the model you wish to delete
\Session::flash('delete_message', 'Model has been successfully deleted.');
return redirect()->back(); // or anywhere else of your choice
}
Hope this helps you out. Happy Coding. Cheers.

Categories