6

I've resource controller in my Laravel project.

Route

Route::resource('products', 'ProductsController');

In the ProductController, I don't want to use show($id) function because there is no need of this function in my project.
When I hit URL belongs to this controller it throws BadController error.
URL example: http://localhost/My-Project/products/123
This URL directly call to the show() function but I've removed that function to improve coding standards. But when any user hit that URL directly then it's throwing an error.

If anyone call that URL directly, it should throw 404 page not found.

Yes, I can handle the URL request by redirecting or other action in show() function, but I don't want to use unnecessary functions in my project.

Is there any way to throw 404 page not found without having the function?

  • 2
    My hint is: do not overthink such issues and leave it as it is, as long as it doesn't break anything. The fact this route is defined doesn't necessarily mean that people will visit it. Nobody will visit it as long as you will not generate those URLs at your web page. Coding standards are important, but don't fall into the hole of perfectionism, code cannot be perfect, it's a black hole. It's always better to spent time to correct/build features, than fixing stuff which nobody will notice. – lchachurski Aug 04 '17 at 07:12
  • @veNuker Thanks for the suggestion. Yes, you are right, nobody will visit on that page but one of the users has visited on that page and we have captured error report on that page so that's why I was finding the solution. –  Aug 04 '17 at 07:25
  • Do you only need to do a `GET` for that page? If so why not just `Route::get` ? – giolliano sulit Aug 04 '17 at 07:40

2 Answers2

15

Resource controllers can be given a subset of actions to register:

Route::resource('products', 'ProductsController', [
    'only' => ['index', 'create', 'store']
]);

This way, you can set explicitly what routes are registered.

When in doubt, use php artisan route:list to see what routes are registered in your application.

Tim van Dalen
  • 1,470
  • 3
  • 21
  • 41
14

Put show inside the except.

Route::resource('products', 'ProductsController', [
    'except' => [ 'show' ]
]);

It'll not register the products.show route so an exception would be thrown.

So, first option would be to handle the exception by adding this below code to app/Exceptions/Handler.php:

use \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttp‌​Exception;

...
...

public function render($request, Exception $e) 
{
    if ($e instanceof MethodNotAllowedHttpException) {
        abort(404);
    }

    return parent::render($request, $e);
}

then edit resource/views/erros/404.blade.php to personalize the page.

Or second option would be to define a full route capture at the end of your routes file to show 404 to undefined routes.

// Catch all undefined routes (place at the very bottom)
Route::get('{slug}', function() {
    return view('errors.404');
})->where('slug', '([A-Za-z0-9\-\/]+)');
Zayn Ali
  • 4,765
  • 1
  • 30
  • 40
  • @Zayan Ali, Thanks for answering but it's not working. It's throwing an error. exception 'Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException' in /var/www/html/My-Project/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php:207 –  Aug 04 '17 at 07:16
  • An alternative here is to not use the `except` array, but to use the `only` array instead. By using `Route::resource('products', 'ProductsController', ['only' => ['index', 'create']])` you can explicitly choose what you need. See https://laravel.com/docs/5.4/controllers#restful-partial-resource-routes – Tim van Dalen Aug 04 '17 at 07:40
  • @TimvanDalen Why would the `only` be a good choice if he just want to ignore the `show` route? – Zayn Ali Aug 04 '17 at 09:05
  • In my opinion, explicitly white-listing is always the better choice. Imagine, for instance, an upgrade to Laravel that adds a new action to resources. If you're using except, this new action is now available in your application. If you're using only, you still get exactly what you require. – Tim van Dalen Aug 04 '17 at 09:49