Laravel: Resource Controller change parameter from ID to Slug - laravel

In my Laravel application I was using the normal routes, such as GET, POST, PUT and all with the various controllers. But as the application progresses, the routes/api.php file is turning out quite bulky. So, I am changing it with the "Resource Controller" syntax, for cleaner and reduced code.
However, earlier I was able to use the "token" or "slug" parameters in the url to fetch the data, for example: show/{token} & show($token) or show/{slug} & show($slug), but now whenever I try these or any other parameter I get 404 not found error. Therefore I am stuck with the default "id" parameter only.
Earlier:
Route::get('/categories', 'CategoryController#index');
Route::get('/categories/{token}', 'CategoryController#show');
Now:
Route::resource('/categories', 'CategoryController');
Is there any way to change the default "id" parameter to any other ..?

For Resource Routing the route parameter is the resource name, first argument, in singular form.
Route::resource('categories', 'CategoryController');
Will give you a route parameter of category. You can see this by running php artisan route:list and looking at the routes that are defined.
If you want to use a different parameter name for a resource you can also do that by overriding the parameter:
Route::resource('categories', 'CategoryController')->parameters([
'categories' => 'something',
]);
Now the route parameter used would be something.
This only has to do with the route parameter name, it has nothing to do with how any binding would be resolved, unless you had an Explicit Route Model Binding defined specifically for a parameter name.
If you are using Implicit Route Model Bindings you would define on your Model itself what field is used for the binding via the getRouteKeyName method. [In the next version of Laravel you will be able to define the field used in the route definition itself.]
Laravel 6.x Docs - Controllers - Resource Controllers - Naming Resource Parameters
Laravel 6.x Docs - Routing - Model Bindings - Implicit Route Model Binding getRouteKeyName

This can also be achieved by changing the customizing the key. In here slug refers to a column in the Category model.
Route::resource('categories', 'CategoryController')->parameters([
'categories' => 'categories:slug',
]);

Related

Laravel resource route doesn't display show in controller

According to the Laravel documentation:
This single route declaration creates multiple routes to handle a
variety of actions on the resource. The generated controller will
already have methods stubbed for each of these actions, including
notes informing you of the HTTP verbs and URIs they handle.
In my route I have this:
Route::resource('admin/companies', 'CompaniesController');
In my controller I have index, create, store, show etc.
Specifically in show I have this:
public function show(Company $company)
{
//
dd('hi');
}
I would expect when I hit this route:
http://127.0.0.1:8000/admin/companies/onecompany
for it to dd my response. Instead I get a 404 error. What am I doing wrong?
This route http://127.0.0.1:8000/admin/companies/onecompany is not a valid route that triggers resource functions according to Laravel documentaion.
The right URL that will trigger the show(Company $company) function is:
//This route will extract the `id` column from the model and show the required record.
http://127.0.0.1:8000/admin/companies/{company}
or
http://127.0.0.1:8000/admin/companies/{id}
Try an existing record in your database;
//Assuming there is a record with an id of 1
http://127.0.0.1:8000/admin/companies/1
cause of your problem seems related to Route model binding
,try it with id in uri.
to see list of your application's routes: php artisan route:list

Laravel 5.6 additional Route::resource() Parameters

I would like to know how to add additional parameters to Laravel's Route Resource without using Query Strings.
I created a controller (CustomerController) with all the built-in resources and then, added the following route:
Route::resource('customers', 'CustomerController');
What i would like to do is add additional parameters to some of the default resources without creating custom routes or using query strings. For example:
Default resource with optional parameter (index):
public function index($page = 0)
{
//...
}
Desired URL:
http://www.example.com/customers
http://www.example.com/customers/{page}
I tried the following, but i get a not found exception (NotFoundHttpException):
Route::resource('customers', 'CustomerController')->parameters([
'index' => 'page'
]);
Is this possible? If so, how can i accomplish it?
Resource Controllers must implement a defined set of methods which are then mapped to the appropriate HTTP verb and path by the router. These methods, paths and verbs form part of a contract that cannot be adjusted, otherwise working with a Laravel application that implements Resource Controllers would be a headache.
Resource Controllers excel in providing the same experience across all Laravel applications, if your application requires behaviour that isn't supported out of the box by Resource Controllers then it is a sign that you should not be using them and should instead register your routes manually.
If you have just one route that needs to implement custom behaviour then you can register some methods instead of all and then choose to register a custom route to your Resource Controllers method, something like:
Route::resource('customers', 'CustomerController')->except([
'index'
]);
Route::get('/customers/{page?}', 'CustomerController#index');
The documentation on Resource Controllers covers except and only.
Try this :
Route::resource('customers', 'CustomerController')->parameters([
'customers' => 'page'
]);
The example above generates the following URIs for the resource's show route:
/customers/{page}
you set the name route: 'index' replace it by the variable : 'customers' name of your ressource

How to declare routes with resources in Laravel 5.2

I have some routes in routes.php in laravel
// Code for rounting admin panel
Route::resource('/admin','Admin\LoginController#index');
Route::resource('/admin/dashboard','Admin\AdminController#index');
Route::resource('/admin/movies','Admin\MovieController#index');
Now when I access url http://localhost/askspidy/admin I want to show login page and it works, but when i access url http://localhost/askspidy/admin/dashboard it should go to dashboard but it's showing me login page only.
I know this is because when it found /admin in any url it's bydefault goes to the route
Route::resource('/admin','Admin\LoginController#index');
I know it's assuming that (/admin) is route to controller and (/dashboard) is the function declared in the controller but I want routing like this only so is there any other solution for this problem.
A RESTful Resource Controller takes over the responsibility of each action. You only need to list the name and the controller:
Route::resource('photo', 'PhotoController');
If you wanted to only use the index method, you’d list it like this:
Route::resource('photo', 'PhotoController', ['only' => [
'index'
]]);
However, it looks like two of your routes are not suitable for resources (login and dashboard), as they should relate to editing a model.
You should instead just use a get() resource instead.
From the docs:
Route::get('user/{id}', 'UserController#showProfile');
So in your case, it would be:
Route::get('/admin','Admin\LoginController#index');
Route::get('/admin/dashboard','Admin\AdminController#index');
Route::resource('/admin/movie','Admin\MovieController');

Laravel 5.2 blade route to resource

The documentation says:
If the named route defines parameters, you may pass the parameters as
the second argument to the route function. The given parameters will
automatically be inserted into the URL in their correct positions:
Route::get('user/{id}/profile', ['as' => 'profile', function ($id) {
//
}]);
$url = route('profile', ['id' => 1]);
If i do have a nested resource route by using Route::resource(...) twice, i will get a named route wich contains a placeholder like
employees.{employee}.images.index
How can i create a route for this nested resource using the blade templating engine?
I thought about
route('employees.{employee}.images.index', ['employee' => $employee->id]);
but that does not work. I know i can "manually" create the routes, but this will make them less maintainable.
Update 1
I know i can name the routes manually and then use the given name. But if there is a way without naming them i would prefer it.
You don't have to add anything like employee into a route name. Run php artisan route:list command and you will see real names of all routes (look at column called Name), created by resource clause. Then just use them like usual:
route('employees.images.index', ['employee' => $employee->id]);
Also, you can name resource routes.

how to pass variable from view to route in laravel

How to pass a variable from view to route in Laravel?
Here's the code at my route.php:
Route::get('/{id}/{id1}', 'WelcomeController#index');
And at welcome.blade.php:
< a href="{{URL::route('/{4}/{5}')}}">test</a>
I want to build a link referencing the route above.
A good approach to do it would be to name your route and then reference it by name, passing the parameters needed. Here is how:
At routes.php:
Route::get('/{id}/{id1}', ['as' => 'welcome_index', 'uses' => 'WelcomeController#index']);
And at your view, you can do this:
test
Notice that the first parameter represent the route name and the second, the parameters for your URL. You can read more here.
The advantages of naming a route is that you can change your route path later and your URL will still work with the code above.

Resources