how to display exception handling error message in laravel - laravel

I have homecontroller in which I have a function storestudent it should able to handle exception, how to do it?
public function storestudent(Request $request)
{
try
{
$student= new student();
$student->sregno= $request['regno'];
$student->save();
return redirect('/home');
} catch (Exception $e){
throw new Execution;
}
}
try-catch exception is not working , help me to fix this please.
Thank you.
this is Execution.php
<?php
namespace App\Exceptions;
use Exception;
class Execution extends Exception
{
//
}
in handler.php
public function report(Exception $exception)
{
if($exception instanceof Execution)
{
echo "invalid register no";
}
parent::report($exception);
}
it gives me this error
This page isn’t working 127.0.0.1 is currently unable to handle this request.
HTTP ERROR 500
anyone help me to display my message and it should redirect to same page.

Here with try and catch you can use Log to keep errors in records and you can check records in log section in application:
public function storestudent(Request $request)
{
try
{
$student= new student();
$student->sregno= $request['regno'];
$student->save();
return redirect('/home');
} catch(Exception e){
$error = sprintf('[%s],[%d] ERROR:[%s]', __METHOD__, __LINE__, json_encode($e->getMessage(), true);
\Log::error($error);
}
}
For more info for Log fascade check this link: Logging.
And another way is to handle exception custom exception handling which you can get here.Error handling
To show error messages on redirect simply use flash messages in laravel without custom exceptions need. following code:
public function storestudent(Request $request)
{
try
{
$student= new student();
$student->sregno= $request['regno'];
$student->save();
\Session::flash('message','Saved successfully');
return redirect('/home');// if you want to go to home
} catch(Exception e){
\Session::flash('error', 'Unable to process request.Error:'.json_encode($e->getMessage(), true));
}
return redirect()->back(); //If you want to go back
}
Flash messages:
#if(Session::has('message'))
<p class="alert {{ Session::get('alert-class', 'alert-info') }}">{{
Session::get('message') }}</p>
#endif
or for more common flash view:
<div class="flash-message">
#foreach (['danger', 'warning', 'success', 'info','error'] as $msg)
#if(Session::has($msg))
<p class="alert alert-{{ $msg }}">{{ Session::get($msg) }}
</p>
#endif
#endforeach
</div>
Controller code:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Candidate;
use App\student;
use Exception;
class Homecontroller extends Controller
{
//function for login page
public function insertReg()
{
return view('login');
}
public function storestudent(Request $request)
{
try {
if ( !student::where('sregno',$request->regno )->exists() ) {
$student= new student();
$student->sregno= $request->regno;
if ($student->save()) {
\Session::flash('message','Saved successfully');
return redirect('/home');// if you want to go to home
} else {
throw new Exception('Unable to save record.);
}
} else {
throw new Exception('Record alreasy exists with same sregno');
}
} catch(Exception $e){
\Session::flash('error', 'Unable to process request.Error:'.json_encode($e->getMessage(), true));
}
return redirect()->back(); //If you want to go back
}
Hope this helps.

Related

I want to redirect to login page when page expired(419) display

I added this code in handler.php
if ($exception instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login_page');
}
but when session destroyed, it does not redirect to login page.
I think you are doing it in a wrong section so in your Handler.php class create a report method
Laravel 7 and higher
public function report(Throwable $e)
{
if ($e instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login_page');
}
}
Laravel 6 and below
public function report(Exception $e)
{
if ($e instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login_page');
}
}
In Laravel 8 or higher, go to app/Exceptions edit Handler.php and update the register method as follows-
public function register()
{
$this->renderable(function (\Exception $e) {
if ($e->getPrevious() instanceof \Illuminate\Session\TokenMismatchException) {
return redirect()->route('login');
};
});
}
in return redirect()->route('login'); change you login to your login route.

Laravel 7.0 - tymon/jwt-auth - check if token is valid

Trying to achieve a login endpoint at a laravel installation by using tymon/jwt-auth (JWT). The login, logout, get userdata is working fine. I would like to have a endpoint for checking the Bearer Token. There is a short way to achieve this via:
Route::get('/valid', function () {
return 1;
})->middleware('auth:api');
If the token is valid, the the HTTP return code == 200 but if not, a 401 code is returned. Since the endpoint is checking a token and not the authenticated communication, I would like to rather have a controller returning true/false regarding valid token with 200 - OK.
I had a look "under the hood" of the modules and that is how far I get (not working):
$tokenKey = $request->bearerToken();
$jws = \Namshi\JOSE\JWS::load($tokenKey);
$jwsSimple = new SimpleJWS($jws->getHeader());
$jwsSimple::load($tokenKey);
$jwsSimple->setPayload($jws->getPayload());
$jwsSimple->setEncodedSignature(explode('.', $tokenKey)[2]);
$tmpVal = $jwsSimple->isValid($tokenKey);
Is there any better approach to achieve this? I assume that there should be a Service Provider for that but could not figure out how to implement this. Thank you in advance.
You could remove the auth:api middleware and then have something like:
return response()->json([ 'valid' => auth()->check() ]);
Maybe this method need you:
public function getAuthenticatedUser()
{
try {
if (! $user = JWTAuth::parseToken()->authenticate()) {
return response()->json(['user_not_found'], 404);
}
} catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
return response()->json(['token_expired'], $e->getStatusCode());
} catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
return response()->json(['token_invalid'], $e->getStatusCode());
} catch (Tymon\JWTAuth\Exceptions\JWTException $e) {
return response()->json(['token_absent'], $e->getStatusCode());
}
return response()->json(compact('user'));
}
Here is the mixed output to achieve status based token validation with laravel and tymon/jwt-auth:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ValidTokenController extends Controller
{
public function __invoke(Request $request)
{
$response = (int) auth('api')->check();
$responseCode = 200;
try {
if (!app(\Tymon\JWTAuth\JWTAuth::class)->parseToken()->authenticate()) {
$response = 0;
}
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
$response = -1;
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
$response = -2;
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
$response = -3;
}
return response()->json($response, $responseCode);
}
}
// Validate Token Controller:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class ValidTokenController extends Controller
{
public function __invoke(Request $request)
{
$response = auth('api')->check();
$responseCode = 200;
if(!$response) {
try {
if (!app(\Tymon\JWTAuth\JWTAuth::class)->parseToken()->authenticate()) {
$response = 0;
}
} catch (\Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {
$response = -1;
} catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
$response = -2;
} catch (\Tymon\JWTAuth\Exceptions\JWTException $e) {
$response = -3;
}
} else {
$response = (int) $response;
}
return response()->json($response, $responseCode);
}
}

Only load route with existent parametre

Im doing a crud, i want to show item data using id, i have this in web.php:
Route::get('update/{id}', 'CrudController#update');
How can I deny that the user changes the id in the path to one that does not exist? That shows only those that exist and those that do not, that do not load?
In your update method, you can do the following:
public function update($id)
{
MyModel::findOrFail($id);
//...perform other actions
}
It will throw a 404 response if the requested $id is a non-existent one.
Then you can catch it if you want in the render() method of app\Exceptions\Handler.php:
use Illuminate\Database\Eloquent\ModelNotFoundException;
.
.
.
public function render($request, Exception $exception)
{
if ($exception instanceof ModelNotFoundException) {
if ($request->wantsJson()) {
return response()->json([
'data' => 'Resource not found'
], 404);
} else {
abort(404);
}
}
return parent::render($request, $exception);
}
Or, If you do not want to go through all the trouble of configuring it in the handler, you could also do:
public function update($id)
{
if (! $model = MyModel::find($id)) {
abort(404);
}
//...perform other actions with $model
}
The abort(404) method takes the user to the default Page not found page of laravel, which is an appropriate thing to do.

Laravel4 old debug page

How can I get the laravel 4 debugger page in laravel 5 debugger
page
here
to
Install the whoops package:
composer require filp/whoops
Then use it to render your exceptions by editing your app/Exceptions/Handler.php:
<?php namespace App\Exceptions;
use Exception;
use Whoops\Run as Whoops;
use Illuminate\Http\Response;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use PragmaRX\Sdk\Services\ExceptionHandler\Service\Facade as SdkExceptionHandler;
class Handler extends ExceptionHandler {
protected $dontReport = [
'Symfony\Component\HttpKernel\Exception\HttpException'
];
public function report(Exception $e)
{
return parent::report($e);
}
public function render($request, Exception $e)
{
if ($this->isHttpException($e))
{
return $this->renderHttpException($e);
}
if (env('APP_DEBUG'))
{
return $this->whoops($e);
}
return parent::render($request, $e);
}
protected function whoops(Exception $e)
{
$handled = with(new Whoops)
->pushHandler(new \Whoops\Handler\PrettyPageHandler())
->handleException($e);
return new Response(
$handled,
$e->getStatusCode(),
$e->getHeaders()
);
}
}

Using ModelNotFoundException

I'm starting out in Laravel and want to discover more about using error handling especially the ModelNotFoundException object.
<?php
class MenuController extends BaseController {
function f() {
try {
$menus = Menu::where('parent_id', '>', 100)->firstOrFail();
} catch (ModelNotFoundException $e) {
$message = 'Invalid parent_id.';
return Redirect::to('error')->with('message', $message);
}
return $menus;
}
}
?>
In my model:
<?php
use Illuminate\Database\Eloquent\ModelNotFoundException;
class Menu extends Eloquent {
protected $table = 'categories';
}
?>
Of course for my example there are no records in 'categories' that have a parent_id > 100 this is my unit test. So I'm expecting to do something with ModelNotFoundException.
If I run http://example.co.uk/f in my browser I receive:
Illuminate \ Database \ Eloquent \ ModelNotFoundException
No query results for model [Menu].
the laravel error page - which is expected, but how do I redirect to my route 'error' with the pre-defined message? i.e.
<?php
// error.blade.php
{{ $message }}
?>
If you could give me an example.
In Laravel by default there is an error handler declared in app/start/global.php which looks something like this:
App::error(function(Exception $exception, $code) {
Log::error($exception);
});
This handler basically catches every error if there are no other specific handler were declared. To declare a specific (only for one type of error) you may use something like following in your global.php file:
App::error(function(Illuminate\Database\Eloquent\ModelNotFoundException $exception) {
// Log the error
Log::error($exception);
// Redirect to error route with any message
return Redirect::to('error')->with('message', $exception->getMessage());
});
it's better to declare an error handler globally so you don't have to deal with it in every model/controller. To declare any specific error handler, remember to declare it after (bottom of it) the default error handler because error handlers propagates from most to specific to generic.
Read more about Errors & Logging.
Just use namespace
try {
$menus = Menu::where('parent_id', '>', 100)->firstOrFail();
}catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
$message = 'Invalid parent_id.';
return Redirect::to('error')->with('message', $message);
}
Or refer it to an external name with an alias
use Illuminate\Database\Eloquent\ModelNotFoundException as ModelNotFoundException;
When you use the render() function in Laravel 8.x and higher versions, you will encounter 500 Internal Server Error. This is because with Laravel 8.x errors are checked within the register() function (Please check this link)
I'm leaving a working example here:
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
public function register()
{
$this->renderable(function (ModelNotFoundException $e, $request) {
return response()->json(['status' => 'failed', 'message' => 'Model not found'], 404);
});
$this->renderable(function (NotFoundHttpException $e, $request) {
return response()->json(['status' => 'failed', 'message' => 'Data not found'], 404);
});
}
}
Try this
try {
$user = User::findOrFail($request->input('user_id'));
} catch (ModelNotFoundException $exception) {
return back()->withError($exception->getMessage())->withInput();
}
And to show error, use this code in your blade file.
#if (session('error'))
<div class="alert alert-danger">{{ session('error') }}</div>
#endif
And of course use this top of your controller
use Illuminate\Database\Eloquent\ModelNotFoundException;

Resources