Having a controller on 404 urls using Laravel 5 - laravel

I need to have a custom controller triggered when user hits a not-existing url or when I programmatically force an App::abort(404).
How can I do it?
My 404 views need some data, and a simple blade View (or a ViewComposer) is not enough.
Thanks
PS catch-all urls is not functional, because they don't catch programmatically launched 404.

Edit the render function of App\Exceptions\Handler class and add something about 404 here:
if ($this->isHttpException($exception) && $this->getStatusCode() == 404) {
// Do what you want...
// You can even use the $request variable
}
Full example:
public function render($request, Exception $exception)
{
if ($this->isHttpException($exception) && $this->getStatusCode() == 404) {
echo 'hello from 404 renderer';
dd($request); // Or you can a view.
}
return parent::render($request, $exception);
}

Try to return a redirect() to your custom Controller instead of a response() from the Handler's render() method if the exception is 404. You can retrieve the the page requested from the $request then right ?
Here is the sample:
public function render($request, Exception $exception)
{
if ($this->isHttpException($exception) && $this->getStatusCode() == 404) {
return redirect(route('route.to.custom.controller'))->with('request', $request);
}
return parent::render($request, $exception);
}
Hope that will help, cheers !

Related

Laravel localization for custom error pages

I have custom error pages e.g. resources/views/errors/404.blade.php everything is working just fine but the localization is not working for error pages. If I change website language the error pages still show in default language I tried in many way but its not working, Can anyone please help me make this work thanks in advance.
I try to make it work via exception handler but don't know how to do that. I can apply language middleware is someone can tell me where is default routes for error pages.
You can also redirect to other pages in App\Exceptions\Handler.php. You can also assign using App::setLocale(). Like this:
public function render($request, Throwable $exception)
{
App::setLocale('en_GB');
/** #var \Symfony\Component\HttpKernel\Throwable $e */
$e = $exception;
$statusCode = $e->getStatusCode();
return $this->isHttpException($exception) && $statusCode == 404 ?
response()->view('frontend.pages.404') :
parent::render($request, $exception);
}
Open app/exceptions/handler.php
find render function paste here
don't for get import this trait
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
public function render($request, Exception $e)
{
if($request->hasCookie('language')) {
// Get cookie
$cookie = $request->cookie('language');
// Check if cookie is already decrypted if not decrypt
$cookie = strlen($cookie) > 2 ? decrypt($cookie) : $cookie;
// Set locale
app()->setLocale($cookie);
}
if($e instanceof NotFoundHttpException) {
return response()->view('errors.404', [], 404);
}
return parent::render($request, $e);
}
thank you guys a little discussion with you guys fixed my problem I get the session's locale value in exception handler that worked for me I am answering it may be can help some one else. Below are the thing I did in App/Exception/Handler.php
use Session;
public function render($request, Throwable $exception)
{
app()->setLocale(Session::get('locale'));
return parent::render($request, $exception);
}
also i moved
\Illuminate\Session\Middleware\StartSession::class,
from web group to global group in kernal.php

laravel MethodNotAllowedHttpException redirect to 404

I use laravel 8 tried to edit my exceptions\handler.php
public function render($request, Throwable $exception)
{
if ($exception instanceof MethodNotAllowedHttpException) {
abort(404);
}
return parent::render($request, $exception);
}
but his gives not 404 but 500 when checking routes where MethodNotAllowedHttpException
One possible solution is to supply your routes/web.php file with a Route fallback. Try adding the following to the bottom of your web routes:
Route::fallback( function () {
abort( 404 );
} );
on Laravel 8 override default handler render function on App\Exceptions\Handler.php
public function render($request, Throwable $exception)
{
if ($exception instanceof MethodNotAllowedHttpException) {
if ($request->ajax() || $request->wantsJson() || $request->expectsJson()) {
//405 for Method Not Allowed
return response()->json(['error' => 'Bad Request'], 405);
}
else {
return parent::render($request, $exception);
}
}
}
don't forget to add use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;to test in Postman set key=>Accept ,value => application/json to test handler
reff: Return a 404 when wrong ttp request type used(e.g. get instead of post) in laravel

Laravel exception if api return json, if website return default page

public function render($request, Exception $exception)
{
if ( $request->route()->getPrefix() == 'api' ) {
some code......
return response()->json($response, $status);
}
return parent::render($request, $exception);
}
I have a website content site & api both.
I want my exception return json when user request api
If user request is not api, it will return the default page.
But when I put logic into function render, the default one got error.
Anyone know how to fix this?
I'm not quite sure what your question is. But you can detect if you should return a JSON response or not using the wantsJson() method. For example the code should instead read to say:
public function render($request, Exception $exception)
{
if ( $request->wantsJson()) {
some code......
return response()->json($response, $status);
}
return parent::render($request, $exception);
}
Laravel should automatically detect this and return a JSON response for exceptions if you are making a JSON request. The fact it isn't doing this, I would check to make sure you are making a JSON request and not a standard HTTP request.
Use $request->wantsJson() and check if the route is prefixed with api:
public function render($request, Exception $exception)
{
if ( $request->wantsJson() && $request->is('api/*')) {
some code......
return response()->json($response, $status);
}
return parent::render($request, $exception);
}
See here for wantsJson() method, and other useful Request methods: https://laravel.com/api/5.7/Illuminate/Http/Request.html#method_wantsJson

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.

Redirect wrong url laravel 5.1

Route :
Route::get('/', function () {
return view('login');
});
and then try to visit this link:
http://www.example.com/wrongurl
How to redirect to specific page if someone trying to access wrong url thats not listed on router ?
You can use the Handler. In the app/Exceptions/Handler.php file you have to add two lines of code in the render functions:
public function render($request, Exception $e)
{
if ($e instanceof ModelNotFoundException) {
$e = new NotFoundHttpException($e->getMessage(), $e);
}
if($e->getStatusCode() == '404') {
return redirect('/');
}
return parent::render($request, $e);
}
You can add as last route this:
Route::get('/{any}', function($any){
redirect('/')'
})->where('any', '.*');
This will redirect any missing get route to /.
If you have learned to use controllers. This will help.
Route::get('/home',Pagecontroller#homepage);
Route::get('/aboutus',Pagecontroller#aboutus);
Route::get('/contactus',Pagecontroller#contactus);
.
.
.
/*last route should be for the unknown url*/
Route::get('/{any}',Pagecontroller#indexpage); //this will redirect to the index page if any unknown routing url is given by mistake or by purpose.
'/{any}' will read all other url which is not declared.
make sure that you use it at the end, after declaration of all other valid routes
you can add the following code in Exception Handler file i.e. app\Exceptions\Handler.php
public function render($request, Exception $exception)
{
if($this->isHttpException($exception)){
if ($exception->getStatusCode()=='404') {
return redirect('/');
}else{
return parent::render($request, $exception);
}
}else{
return parent::render($request, $exception);
}
}

Resources