I'm currently working on a project with my friend. He follows this method of writing codes. Is it good or bad? I'm also not that much experience developer.
public function store(Request $request)
{
try
{
$comment = new TicketComment();
$comment->content = $request['comment'];
$comment->user_id = Auth::user()->id;
$comment->ticket_id = $request['ticketId'];
$comment->save();
$ticket = Ticket::where('id', '=', $comment->ticket_id)->first();
$ticket->updated_at = $comment->created_at;
$ticket->update();
}
catch(Exception $e)
{
request()->session()->flash('unsuccessMessage', 'Failed to add comment !!!');
return redirect()->back();
}
request()->session()->flash('successMessage', 'Comment has been successfully added !!!');
return redirect()->back();
}
Don't have a broad Exception catch block. Only catch exceptions you expect to be thrown in that block that way you can properly log unexpected exceptions and fix any other bugs in your code that may have caused those, instead of hiding them from yourself.
If you must do this then it might be in the context of something like:
public function store(Request $request)
{
try
{
$comment = new TicketComment();
$comment->content = $request['comment'];
$comment->user_id = Auth::user()->id;
$comment->ticket_id = $request['ticketId'];
$comment->save();
$ticket = Ticket::where('id', '=', $comment->ticket_id)->first();
$ticket->updated_at = $comment->created_at;
$ticket->update();
}
catch(Exception $e)
{
if (!($e instanceof SQLException)) {
app()->make(\App\Exceptions\Handler::class)->report($e); // Report the exception if you don't know what actually caused it
}
request()->session()->flash('unsuccessMessage', 'Failed to add comment !!!');
return redirect()->back();
}
request()->session()->flash('successMessage', 'Comment has been successfully added !!!');
return redirect()->back();
}
This way any unexpected exceptions will still be reported and you can go through your logs later to fix any bugs that are causing them.
As a reminder since PHP 7.1 you can have a union of exceptions in a catch block (Reference) e.g.
try { }
catch (ExceptionType1|ExceptionType2 $e) {
}
This way you can handle the exceptions you know you can handle and let Laravel handle the ones you are not sure how to handle.
Note that you generally don't have to have try-catch blocks in controller code, you can always use the exception handler to do the flash/redirect back combination for all unhandled exceptions if that is your preferred way of handling them.
It is allways good to handle the errors. However, Laravel has built in error handling, which ease this process. This does not mean you dont need the try catch block.
Read more about laravel error handling: https://laravel.com/docs/5.8/errors
Even that laravel has his own built in error handling you better use try & catch.
Don't use it on development mode but on production mode. The use of try & catch is user friendly, which means that user will not see the traditional page with the error generated from laravel (in case of any error), but will see your default message.
Example of how to use it:
public function index()
{
try {
return view('index.blade.php');
} catch (\Exception $exception) {
\Log::error($exception);
return redirect()->back()->with(['message' => 'There was an error']);
}
}
If you see this part \Log::error($exception);, it means that the error generated from laravel will be registered on logs file under storage/logs/laravel.log so you as e developer can see the problem with that method. On the other part if something goes wrong with accessing the page: view('index.blade.php') the user will be redirected back to the previous page with a message saved in session, which is: 'There was an error'.
To catch the message in case of errors in your blade you should:
#if (session('message'))
<div class="container">
<div class="alert alert-danger text-center">{{ session('message') }}</div>
</div>
#endif
Happy coding!
here is how I handled the same. I logged the error instead of returning it to user interface.
public function postData()
{
try
{
//your logics to post goes here
}
catch (\Exception $exception) {
if (!($exception instanceof \SQLiteException)) {
app()->make(\App\Exceptions\Handler::class)->report($exception); // Report the exception if you don't know what actually caused it
}
Alert::toast('Error Toast', 'An error occurred');
\Log::error($exception);
return redirect()->back();
}
Alert::success('SuccessAlert', 'alert');
return back();
}
Related
In my controller, I used the method firstOrFail() for a database query with Eloquent. When in debug mode, I get a Laravel error message with the content Illuminate\Support\ItemNotFoundException.
However, I'd like to return a redirect() or mabye back() instead of showing this error screen. How can I do that?
use php try catch, to override the behaviour of error catching,
try {
// your functional code
} catch (Illuminate\Support\ItemNotFoundException $exception ) {
//your redirect command , the code here will be executed if there is an exception with type ItemNotFoundException
}
if you want to catch all errors, you need to use the General Exception class which is the parent of all Exceptions
try {
// your functional code
} catch (\Exception $exception) {
//your redirect command , the code here will be executed if there is any exception
}
if you want to get the exception message to log it or any customization , you can use the method : getMessage() , in our case will be $exception->getMessage()
Instead of firstOrFail() use first() and use condition to redirect back, for example:
$item = Item::where('slug', $slug)->first();
if (! $item) {
return redirect()->back();
}
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.
I have set the debug to true on .env file. Added the exceptions correctly but when i am passing invalid or not exist in my database its showing me 404 error but here I put the custom error handling value. Here is my code. (also I put "Use Expectation;" on top so no need of \Expectation)
public function show($id)
{
//only one author with id
try
{
$event = Event::with('eventCategory')->findOrFail($id);
return new EventsResource($event);
//return one author
}
catch(Expectation $e)
{
report($e);
return response()->json(['status'=> false, 'message'=>'invalid data'],200);
}
}
Do you mean Exception? Because in your question it's Expectation...
As #user3532758 is implying, you probably want to be catching the base Exception not Expectation.
Also make sure you are referencing Exception from the root namespace, assuming the code you have shown is in a Controller:
try {
...
} catch (\Exception $e) {
...
}
PHP Manual - Classes - Exception
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
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.