Working on Laravel 4, I created following route and able to fetch ID:
Route::get('details/{ID}', 'Exchange#details');
Issue is when I miss ID in route then it shows: NotFoundHttpException error. I want to avoid this. How do I proceed? Even in global.php I added following but did not work:
App::missing(function($exception)
{
print "Not Found";
// return Response::make(
// View::make('errors/404')
// , 404);
});
Controller Method
public function details($exchangeID)
{
echo "Print Details";
echo $exchangeID;
if(intval($exchangeID) == 0)
{
throw new NotFoundException;
}
}
Update: Recommendation of redirecting to 404 works but I am more interested to detect missing ID and load my Own View with proper message information instead of showing plain 404 page.
I would try something like this
# file routes.php
Route::get('{ID?}', 'SomeController#getDetails')
# file SomeController.php
function getDetails($ID=null) {
if empty($ID) {
return Redirect::to('PREVIOUS PAGE')
->withInput()
->with('error', 'invalid value');
}
}
Try like this :
App::missing(function($exception)
{
return View::make('errors.404');
});
The view is located in views/errors/404.blade.php
Related
when i delete something from database ... lets say a blog , i might want to redirect the link for that blog to another link instead of 404 page
i have a table called setting_redirects :
setting_redirects : id , deleted_link , redirect_link
i'll store the deleted links and new link in this table
this is how i show a blog
function show( $blog_id ){
$blog = Blog::findOrFail($blog_id);
}
the problem is if it's not found findOrFail will automatically redirect user to 404 page ... i want to be able to checksetting_redirects to see if a redirect is available for that blog .... if so redirect to that new link otherwise go to 404
something like this
function show( $blog_id ){
$blog = Blog::find($blog_id);
if(!$blog)
{
$redirect_available = SettingRedirect::where('deleted_link ' , Request::url() ) ->first();
if($redirect_available )
return redirect( $redirect_available-> redirect_link );
else
abort(404);
}
}
but i want this for all my tables not only blogs and i dont want to write this code in all of my controllers
is there anyway to do this without changing all my controllers ? maybe a middleware before going to 404 page ?
findOrFail throws a ModelNotFoundException. I think you can simply catch and rethrow it.
try {
$blog = Blog::findOrFail($blog_id);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
$redirect_available = SettingRedirect::where('deleted_link', Request::url())->first();
if ($redirect_available)
return redirect($redirect_available->redirect_link);
throw $e;
}
Alternatively, you can put this logic in the app/Exceptions/Handler.php file inside the register() method.
<?php
namespace App\Exceptions;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Throwable;
class Handler extends ExceptionHandler
{
public function register()
{
$this->renderable(function (NotFoundHttpException $e, $request) {
// this is to make sure the exception was caused by a findOrFail operation
if ($e->getPrevious() instanceof ModelNotFoundException) {
$redirect_available = SettingRedirect::where('deleted_link', $request->url())->first();
if ($redirect_available) {
return redirect($redirect_available->redirect_link);
}
}
});
}
}
The reason why the first line is $this->renderable(function (NotFoundHttpException $e, $request) { ... }) instead of$this->renderable(function (ModelNotFoundException $e, $request) { ... })
is because Laravel does this weird thing of transforming ModelNotFoundException into NotFoundHttpException before it's available to the exception handler.
I think need to change status of that particular record while deleting action, code on 404, if query executeble then include "mypage.php"; else would show default 404 page
I have the next code:
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
return view('users.list',compact("lang","class"));
})->where('class', '[a-z]+');
Route::get('/{lang}/user/{user}', function ($lang,$user) {
return view('users.user',compact("lang","user"));
});
When condition in where is false, how can I send it directly to 404 when sort-by- is for example a number? The problem is that it goes to secondary route as an user.
For example:
/en/user/sort-by-name is ok
/en/user/sort-by-4446 must show 404 page
I know that i can do another route just between them with
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
return \Response::view('errors.404',array(),404);
})->where('class', '.*');
but this seems ugly, i would like in same sentence
Basically, you may do this
Route::get('/{lang}/user/sort-by-{class}', function ($lang,$class) {
if (is_numeric($class)) {
abort(404, 'Your reason');
}
return view('heros.list',compact("lang","class"));
});
Though, using closures in routes is a bad practice because they cannot be serialized in production mode. That's why you should use a controller to return your view, and assign a middleware to this route which will check your class and abort the request if needed.
I just learn CodeIgniter 4 Framework. How to customize my 404 page not found?
Go to your Routes.php file and find
$routes->set404Override();
Now , If you want to display just an error message then write
$routes->set404Override(function(){
echo "your error message";
});
instead of
$routes->set404Override();
Or
If you want to return a view then write like below:
$routes->set404Override(function(){
return view('your_filename');
});
instead of
$routes->set404Override();
// Would execute the show404 method of the App\Errors class
$routes->set404Override('App\Errors::show404');
// Will display a custom view
$routes->set404Override(function()
{
echo view('my_errors/not_found.html');
});
To customize your 404 page, modify app/Views/errors/html/error_404.php to your liking.
For custom error messages
in Config\routes.php
// Custom 404 view with error message.
$routes->set404Override(function( $message = null )
{
$data = [
'title' => '404 - Page not found',
'message' => $message,
];
echo view('my404/viewfile', $data);
});
in my viewfile, to display error:
<?php if (! empty($message) && $message !== '(null)') : ?>
<?= esc($message) ?>
<?php else : ?>
Sorry! Cannot seem to find the page you were looking for.
<?php endif ?>
from my controller:
throw new \CodeIgniter\Exceptions\PageNotFoundException('This is my custom error message');
We have a DB with 100 users.. for example
And here is the route
Route::get('/users/{user}/edit', 'UserController#edit');
Here is the method
public function edit(User $user)
{
$hi = 'Hello';
return $hi;
}
Ok.. if I do something like this
http://localhost/users/99/edit | WORKS
http://localhost/users/100/edit | WORKS
http://localhost/users/101/edit | PROBLEM
How to solve when the user change the value from URL with an inexistent record..?
In this case I would pass the user id as a parameter rather than explicit binding:
Route::get('/users/{userId}/edit', 'UserController#edit');
When a model is not found you will get a ModelNotFoundException exception thrown, you can catch it and treat this case
Controller:
use Illuminate/Database/Eloquent/ModelNotFoundException;
[...]
public function edit($userId)
{
try{
$user = User::find($userId);
//do some stuff
} catch (ModelNotFoundException $e){
//treat error (log the activity, redirect to a certain page)
//or display a 404 page
//dealer's choice
}
}
In your case the user can't be found, which is a 404:
public function edit(User $user)
{
$user = false; // dummy/example
if ($user) {
return $your_results;
} else {
return view('errors.404');
// assuming you have a folder called 'errors' inside your 'views' folder
// and the file name is `404.blade.php`
// and are using blade files.
}
}
If the user can be found, show whatever you need to, else, show a 404 blade view.
A little late, but it is an useful question.
To suppress the error message you can set the debug mode in the (dot)ENV file to false APP_DEBUG=true. Due to the route model binding, the other solutions above won't help you, because if the model is not found, you won't get into the controller. Unless you don't get the model but only the id or slug etc. and then make a query against the database within the function.
I am with a bit of a stuggle here. I managed to create the dynamic URL using the following code:
Home Page Controller
$satellites = DB::table('satellites')->get();
return view('pages/home', ['satellites' => $satellites]);
Blade File
#foreach($satellites as $satellite)
<li>{{$satellite->satname}}</li>
#endforeach
web.php
Route::get('{norad_cat_id}', 'Satellite#show');
Controller
public function show($norad_cat_id)
{
return view('pages/satellite');
}
The URL generated is: mysite.com/12345 (where 12345 is the norad_cat_id).
This code manages to create the dynamic URLs using the norad_cat_id from the database - which is what I want. The problem is that I can replace the URL with anything and it still creates a page (ie. replace the 12345 with something not from the database and a page is still created).
What I want is only for a URL to be generated only with the norad_cat_id and if there is no matching norad_cat_id in the database, display a 404 page.
In the show method add a fetch from database if there is no record just abort
public function show($norad_cat_id)
{
$satellite = DB::table('satellites')->where('norad_cat_id', $norad_cat_id)->first();
if( ! satellite){
return abort(404);
}
return view('pages/satellite');
}
PS: abort will automatically redirect to your resources/views/errors/404.blade.php
You can do this multiple ways
Create a regex for norad_cat_id
The example shows nummeric ([0-9]+)
Route::get('{norad_cat_id}', 'Satellite#show')->where(['norad_cat_id' => '[0-9]+']);
Use findOrFail() and on fail show the 404.
try
{
$user = Satellites::findOrFail($id);
return view('norad_cats');
}
// catch(Exception $e) catch any exception
catch(ModelNotFoundException $e)
{
return view('404');
}
You can throw 404 in your controlller (for example). Just check if records exists in database - if not then return error.
Example:
public function show($cat_id)
{
$sattelites = DB::table('sattelites')->where('norad_cat_id', $cat_id)->get();
if ($satellites === NULL)
{
\App::abort(404);
}
return view('pages/sattelite', [
'satellites' => $satellites
]);
}
I think you get the idea.
Here's an example using query builder which is what I assume you're using:
public function show($norad_cat_id)
{
$norad_cat_data = DB::table('satellites')->where('norad_cat_id', $norad_cat_id)->get();
if (!is_null($norad_cat_id)
{
return view('pages/satellite');
}
\App::abort(404);
}