I'm using the following exception handler in the handler.php file :
public function render($request, Exception $e)
{
if ($e instanceof CustomException) {
return response()->view('errors.404', [], 404);
}
return parent::render($request, $e);
}
It is working fine until I include the header to the 404.blade.php file :
#include('includes.header')
I start receiving this error :
Session store not set on request. (View: C:\xampp\htdocs\sharp\resources\views\includes\header.blade.php)
Because the route wasn't found, the web middleware, which starts the session, was never applied.
I'm not a fan of this answer, but it is relevant.
Instead, consider passing a parameter to your nested template specifying if the section of your template calling Auth::user() should be rendered, via the #if blade directive.
Something like:
#include('includes.header', ['omit_auth' => true])
then in your header template:
#if (!empty($omit_auth))
{{ Auth::user()->name }}
#endif
Related
I am trying to catch PostTooLargeException error and redirect it with error message. Here's the handler which I wrote
if ($exception instanceof \Illuminate\Http\Exceptions\PostTooLargeException) {
return redirect()->back()->withErrors(['msg', 'Post is too large']);
}
My create page has function to check for errors and it works when im testing on controller and through routes.
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
The redirect works however the i can't get the error message and it wont display anything. Am i missing something?
Update
The post below helped me but there was another problem.And that problem was php.ini post_max_size, as i increased it everything started to work. Combined with the code below of course.
You can add your redirect handler inside render method of app/Exceptions/Handler.php like below :
/**
* Render an exception into an HTTP response.
*
* #param \Illuminate\Http\Request $request
* #param \Exception $exception
* #return \Illuminate\Http\Response
*/
public function render($request, Exception $exception)
{
if ($exception instanceof \Illuminate\Http\Exceptions\PostTooLargeException) {
return \Illuminate\Support\Facades\Redirect::back()->withErrors(['msg' => 'The Message']);
}
return parent::render($request, $exception);
}
Then, it will send you the errors in flash session to be shown on frontend.
I think you are trying to use 'msg' as the key for 'Post is too large', and if that's the case it should be an associative array.
->withErrors(['msg' => 'Post is too large'])
But, even with the code you have it should be displaying an error for 'msg' and 'Post is too large' in your ul element. So you would have 2 list items within that container. Not seeing anything technically wrong with what you shared to where you would see no errors on the redirect.
I'm developing a Laravel 5.6 API and I'm using Resources and Collections, Route Model Binding.
To show an item, I currently use following code in my controller:
public function show(Todo $todo)
{
TodoResource::withoutWrapping();
return new TodoResource($todo);
}
In the Exceptions > Handler.php I have the following:
public function render($request, Exception $exception)
{
// This will replace our 404 response with
// a JSON response.
if ($exception instanceof ModelNotFoundException) {
return response()->json([
'error' => 'Resource not found'
], 404);
}
return parent::render($request, $exception);
}
This works perfectly when the item is found in the database. If the item is not in the database I get a (when using a browser):
"Sorry, the page you are looking for could not be found"
When using POSTMAN rest client, I'm getting
{
"message": "No query results for model [App\\Todo].",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
....
....
I would like to simply retrieve a 404 error with text "Resource not found", using both a browser or POSTMAN.
* Update with Routing info *
In my api.php, I have the following:
Route::apiResource('todos', 'TodoController');
Route::fallback(function () {
return response()->json(['message' => 'Not Found!'], 404);
});
In web.php, I have:
Route::Resource('todos', 'TodoController');
What is the best way to achieve this?
Make sure to alias the exception class you are checking for.
use Illuminate\Database\Eloquent\ModelNotFoundException;
Without this you are checking for an instance of App\Exceptions\ModelNotFoundException.
I'm trying to show a custom error page, which I'd like to appear if the error wasn't a 'page not found' or a authentication issue (e.g. trying to access a page which the user doesn't have access to). I'm using the code below in Laravel 5.3's Handler.php. While the 404 part works, the authentication part doesn't (triggering this error just returns the 500 page instead). What am I missing?
public function render($request, Exception $e)
{
if ($e instanceof NotFoundHttpException || $e instanceof AuthorizationException || $e instanceof AuthenticationException) {
return parent::render($request, $e);
}
else {
return response()->view('errors.500', [
'sentryID' => $this->sentryID,
], 500);
}
}
Edit : Looks like you want to handle all the global error pages. Laravel uses symfony's exception handler to generate the error page text and style. This can be found at
vendor/symfony/debug/ExceptionHandler.php
It's used in vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php as
use Symfony\Component\Debug\ExceptionHandler as SymfonyExceptionHandler;
To handle every error and exception you can extend the method prepareResponse to app/Exceptions/Handler.php and make appropriate changes.
protected function prepareResponse($request, Exception $e)
{
if ($this->isHttpException($e)) {
return $this->toIlluminateResponse($this->renderHttpException($e), $e);
} else {
return $this->toIlluminateResponse($this->convertExceptionToResponse($e), $e);
}
}
You can check the underlying working of this method in vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php
End edit
You don't need to mess in the render method for this. Out of the box laravel searches for error views and renders them if available based on the error code. So for 404 and 500 you could just create the following two views and customize it in there.
resources/views/errors/404.blade.php
resources/views/errors/500.blade.php
This views get the exception, status and header information for you to display if needed. They are called like so
return response()->view("errors.{$status}", ['exception' => $e], $status, $e->getHeaders());
For the authentication check. Laravel calls the unauthenticated method in app/Exceptions/Handler.php when a user is unauthenticated. This code by default redirects the users to login page or shows a json response. You can make you changes here.
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest('login');
}
I have a controller where i do something like this
return abort('401', 'User cannot be found');
How do i access the message in my view (errors/401.blade.php).
/************* 401.blade.php ***********/
{{ dd($exception) }}
If i die dump $exception in my view i get this
HttpException {#203 ▼
-statusCode: "401"
-headers: []
#message: "User cannot be found"
#code: 0
#file: "C:\laravel\framework\src\Illuminate\Foundation\Application.php"
#line: 882
-trace: array:54 [▶]
}
How to do i access the message variable?
Well, in Laravel documentation said this:
Custom HTTP Error Pages
Laravel makes it easy to return custom error pages for various HTTP
status codes. For example, if you wish to customize the error page for
404 HTTP status codes, create a resources/views/errors/404.blade.php.
This file will be served on all 404 errors generated by your
application.
The views within this directory should be named to match the HTTP
status code they correspond to.
I think you have to create a 401.blade.php view and then your code will work.
As showed here: https://stackoverflow.com/a/29633624/4425719
Extend Laravel's Exception Handler,
Illuminate\Foundation\Exceptions\Handler, and override
renderHttpException(Symfony\Component\HttpKernel\Exception\HttpException
$e) method with your own.
If you haven't run php artisan fresh, it will be easy for you. Just
edit app/Exceptions/Handler.php, or create a new file.
Handler.php
<?php namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
class Handler extends ExceptionHandler {
// ...
protected function renderHttpException(HttpException $e) {
$status = $e->getStatusCode();
if (view()->exists("errors.{$status}")) {
return response()->view("errors.{$status}", compact('e'), $status);
}
else {
return (new SymfonyDisplayer(config('app.debug')))->createResponse($e);
}
}
}
And then, use $e variable in your 404.blade.php.
i.e.
abort(404, 'Something not found');
and in your 404.blade.php
{{ $e->getMessage() }}
For other useful methods like getStatusCode(), refer
Symfony\Component\HttpKernel\Exception
According to Laravel 4 docs I can throw a 404 with a custom response:
App::abort(404, 'My Message');
I can then handle all of my 404s with a custom page:
App::missing(function($exception)
{
return Response::view('errors.missing', array(), 404);
});
How can I pass 'My Message' through to the view in the same way that the generic Laravel error page does.
Thanks!
You can catch your message through the Exception parameter
App::missing(function($exception)
{
$message = $exception->getMessage();
$data = array('message', $message);
return Response::view('errors.missing', $data, 404);
});
Note: The code can be reduced, I wrote it like this for the sake of clarity.
In Laravel 5, you can provide Blade views for each response code in the /resources/views/errors directory. For example a 404 error will use /resources/views/errors/404.blade.php.
What's not mentioned in the manual is that inside the view you have access to the $exception object. So you can use {{ $exception->getMessage() }} to get the message you passed into abort().