I'm just playing around with my code and notice that one of my controller is returning empty attributes but the other is returning my data fine.
I have two controllers, OneController and TwoController with both resource and same model in it. I use the php artisan make:controller OneController --model==MyModel
and php artisan make:controller TwoController --model==MyModel. two different controller with similar model.
Both have
public function show(MyModel $myModel)
{
dd($myModel);
}
But only theOneController#show is returning my data...
My links are like this
{{route('one.show', $myModel->id) }}
and
{{route('two.show', $myModel->id) }}
I also run php artisan route:clear
I change my TwoController#show to show($id) and it is working fine but I can't ignore that the same code is giving me different results and I want my code to be as clean as possible.
Is there any rule in Laravel 5.8 that you can only use One controller per model on a resource?
Am I missing something?
Thanks!
You're injecting the model you want into your controller action, instead of fetching the record yourself using the ID parameter. Because you're using this you need to adhere to certain rules - read the route model binding documentation for more information.
Long story short: the name of the parameter in the route definition and the name of the argument in the controller action need to match in order for route model binding to take place - otherwise a new model instance will be passed to the method.
Because you're using the Route::resource() method instead of defining routes yourself Laravel will automatically call the parameter by the path you pass in. You can verify this by running php artisan route:list.
To achieve this with a resource you'll need to manually name the resource parameters, which would effectively be something like Route::resource('two', 'TwoController')->parameters(['two' => 'myModel']) where myModel would be your model name.
Related
I'm using same route name for the get & post methods in route. those routes are using for the same purpose.
ex : I'm calling to load add view form using get route
Route::get('add', 'UserController#addView')->name('user.add');
then,
I'm calling to store data in that form using post route
Route::post('add', 'UserController#store')->name('user.add');
is there any issue , If I use the same route name like this?
No, you can not use the same name for 2 different routes as is stated in the documentation if you really need to name the routes you should look for different names, but if there's no need to have named routes you can have each url with its method like:
Route::get('/your-url', 'App\Http\Controllers\UserController#addView');
Route::post('/your-url', 'App\Http\Controllers\UserController#store');
If you are making a CRUD you can have:
Route::resource('user', UserController::class);
This will create all the urls needed for a CRUD:
Actually you have same name for both routes i.e., name('user.add'). Change that.
Yes you can get issues in future. For example, I had issues after functionality update - I've updated route interface (added some fields) and new fields does not appeared in result after opening URL.
Please run command php artisan optimize to see is it all ok.
I am creating Elequent models with the following structure:
Event->hasMany(Invite)
Invite->belongsTo(Event)
I am creating a controller with the following artisan command:
php artisan make:controller -mInvite -pEvent EventInvitesController --resource
Now if I create custom routes like:
Route::get('event/{event}/invite', 'EventInvitesController#index')->name('event.invites.index');
Route::post('event/{event}/invite', 'EventInvitesController#store')->name('event.invites.store');
Route::get('event/{event}/invite/{invite}', 'EventInvitesController#show')->name('event.invites.show');
Route::put('event/{event}/invite/{invite}', 'EventInvitesController#update')->name('event.invites.update');
Route::delete('event/{event}/invite/{invite}', 'EventInvitesController#destroy')->name('event.invites.destroy');
Route::get('event/{event}/invite/{invite}/edit', 'EventInvitesController#edit')->name('event.invites.edit');
Then everything works fine. But I was wondering if there is a way to do this like
Route::resource('event-invites', 'EventInvitesController');
When I've tried to do this the routes only have a single {event_invites} paramater when I need two.
Is there a way to enable routing for the parent model in Route::resource()?
If not how would I go about extending Route to provide such a method?
Use dot notation:
Route::resource('events.invites', 'EventInvitesController');
This would create a set of routes for posts that include the user identifier. For example:
The ‘index’ route:
http://example.com/events/1/invites
The ‘show’ route: http://example.com/events/1/invites/10
Check out the documentation here:
https://laravel.com/docs/5.1/controllers#restful-nested-resources
So if you do something like
$ artisan make:model TurboClown
$ artisan make:controller TurboClownController -r --model=TurboClown
So at this point it's possible to add something like:
Route::resource('clowns','TurboClownController');
To your routes/web.php. Now I have routes like clowns/{clown} when I routes:list with artisan.
However, my show function is like:
public function show(TurboClown $turboClown)
Which when you return $turboClown will just give [] as a response when you request "/clowns/3/" for example. It took me a while to figure out that if I change $turboClown parameter to $clown, I get a JSON TurboClown as a response.
So in a sense, I solved my problem. But I'm curious about a couple points:
To me, https://laravel.com/docs/5.4/controllers#restful-naming-resource-route-parameters reads as if I could add ['parameters' => ['clown' => 'turboClown'] and then show() would work using "turboClown", but it does not.
According to https://laravel.com/docs/5.4/routing#route-parameters : " Route parameters are injected into route callbacks / controllers based on their order - the names of the callback / controller arguments do not matter." But it looks like the name of the parameter does matter in this case?
So I am looking for some kind of clarification on those two points, what am I missing?
You are doing it wrong. The documentation says:
The parameters array should be an associative array of resource names and parameter names
So in your case the resource name is "clowns" (and not "clown") and you want for this resource name the parameter to be "turboClown:
Route::resource('clowns', 'TurboClownController', ['parameters' => [
'clowns' => 'turboClown'
]]);
I agree that this point can be confusing. Maybe you already know that but what you are doing here is called implicit route model binding. And for it to be "implicit", there is one rule overruling the one you mentioned:
Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
Also for this pretty cool thing to work the parameter has to match an identifier for the corresponding model (in your case TurboClown).
So now combining those two points you should be able to do this:
In your routes file:
Route::resource('clowns', 'TurboClownController', ['parameters' => [
'clowns' => 'turboClown'
]]);
In TurboClownController:
public function show(TurboClown $turboClown)
{
return $turboClown;
}
Now let's say you want to retrieve the turbo clown with the identifier 5. You can cal the route http://example.dev/clowns/5.
Hope it helped.
I am new to Laravel 5 and I am trying to use the new Form Request to validate all forms in my application.
Now I am stuck at a point where I need to DELETE a resource and I created a DeleteResourceRequest for just to use the authorize method.
The problem is that I need to find what id is being requested in the route parameter but I cannot see how to get that in to the authorize method.
I can use the id in the controller method like so:
public function destroy($id, DeletePivotRequest $request)
{
Resource::findOrFail($id);
}
But how to get this to work in the authorize method of the Form Request?
That's very simple, just use the route() method. Assuming your route parameter is called id:
public function authorize(){
$id = $this->route('id');
}
You can accessing a Route parameter Value via Illuminate\Http\Request instance
public function destroy($id, DeletePivotRequest $request)
{
if ($request->route('id'))
{
//
}
Resource::findOrFail($id);
}
Depending on how you defined the parameter in your routes.
For my case below, it would be: 'user' not 'id'
$id = $this->route('user');
Laravel 5.2, from within a controller:
use Route;
...
Route::current()->getParameter('id');
I've found this useful if you want to use the same controller method for more than one route with more than one URL parameter, and perhaps all parameters aren't always present or may appear in a different order...
i.e. getParameter('id')will give you the correct answer, regardless of {id}'s position in the URL.
See Laravel Docs: Accessing the Current Route
After testing the other solutions, seems not to work for laravel 8, but this below works
Route::getCurrentRoute()->id
assuming your route is
Route::post('something/{id}', ...)
I came here looking for an answer and kind of found it in the comments, so wanted to clarify for others using a resource route trying to use this in a form request
as mentioned by lukas in his comment:
Given a resource controller Route::resource('post', ...) the parameter you can use will be named post
This was usefull to me but not quite complete. It appears that the parameter will be the singular version of the last part of the resource stub.
In my case, the route was defined as $router->resource('inventory/manufacturers', 'API\Inventory\ManufacturersController');
And the parameter available was manufacturer (the singular version of the last part of the stub inventory/manufacturers)
you will get parameter id if you call
request()->route('id')
OR
$this->route('id')
if you're using resource routing, you need to call with the resource name
// eg: resource
Route::resource('users', App\Http\Controllers\UserController::class);
$this->route('user')
in Terminal write
php artisan route:list
to see what is your param name
Then use
$this->route('sphere') to get param
I am new to laravel 4 framework but was previously working on CI and CakePHP, i have some problems with routes in it (i may sound nerd, so bear with me.)
-> If i have 3 controller userController,adminController,editorController and many methods inside them, do i need to define routes for every methods inside it (ofcourse i am not using ResourceFull controller for them). Can't i have something by which the methods can be accessed by using the controllername followed by method name like we do in other frameWork.
E.g usersController have manageUser method, i wnt to access it like
http://localhost/project/users/manageUser
-> What is use of defining a route using Route::controller('users', 'UserController'); or restfull controller?
Thanks in advance :)
If you write
Route::controller('users', 'UserController')
runs the default function (index of all the objects), but you can write:
Route::get('/users', 'userController#function');
or
Route::post('/users', 'userController#function');
this route shows to Laravel what controller and function can call when you write this route, the diference is if you pass the parameters with get or post mode.
Hope I help you