Laravel 8 resource controller not fetching model - php

In Laravel 7 fetching a model was pretty straightforward, i just needed to setup mi resource route and make a get to the address:
http://localhost/test/public/employee/1
But i cant make it work on Laravel 8, according to my understanding i just need to do this:
public function show(Employee $employee)
{
dd($employee);
}
But dd only returns an empty class:
If i do this:
public function show(Employee $employee)
{
dd(Employee::find(1));
}
dd returns the correct data:
Route::resources([
'employee' => EmployeeController::class,
]);
Can somebody help me find what am i missing?
Regards...

Route::resource('employee', EmployeeController::class);
https://laravel.com/docs/8.x/controllers#resource-controllers

Your Route must have the same variable like
Route::get('/employee/{employee}', 'EmployeeController#show');
And ensure you have binding middleware enabled for this route. ->middleware(['bindings']);
Updating for Resource routing:
Route::resource('/employee', 'EmployeeController')->middleware('bindings');

The problem was that i was naming the routes in spanish:
Route::apiResource('empleados', EmployeeController::class);
And because of this Laravel is expecting to receive the model encapsulated in a spanish verb class (empleados instead of employee), So i needed to rename the parameter inside the method controllers to receive the correct model:
public function show(Employee $empleado)
{
return $empleado;
}

Related

Lumen 7 controllers bug

I am using lumen 7 framework.
I had a bug. In the web.php file I put:
$router->get('/getAll/{param1:[0-9]+|2A|2B}/{param2:[0-9]+}', 'TestController#getAll');
So, in the TestController, I create the function like that :
public function getAll($param1, $parm2)
{
....
}
The isssue is :
Illuminate\Contracts\Container\BindingResolutionException: Unable to resolve dependency [Parameter #1 [ $param2 ]] in class App\Http\Controllers\TestController
I did some tests, I add this bloc to provider, but it didn't work.
$this->app->singleton(\Illuminate\Contracts\Routing\ResponseFactory::class, function() {
return new \Laravel\Lumen\Http\ResponseFactory();
});
Also, I checked if I had done something wrong in the web.php file but I changed the function in the controllers to :
public function getAll($param1)
{
$parm2=1;
....
}
and it works fine.
How can I fix this bug, because in the url I need the two params.
Thanks,
The issue was that the names in controller and in the route was not the same.
The names in the controller was a little different from the route.
I did a upgrade from lumen 5.6 to lumen 7.0 and I thinks since Lumen 5.8 the names must be the same.
In route, you're passing only one param that's why you're getting this error.
$router->get('/getAll/{param1:[0-9]+|2A|2B}/{param2:[0-9]+}/{param2:[0-9]+|2A|2B}/{param2:[0-9]+}', 'TestController#getAll');
In controller.
public function getAll($param1, $param2)
{
....
}

Laravel Model not binding in controller method

I have a Laravel model PurhaseOrder and a controller PurchaseOrdersController with a method show
If I typecast the method with an an interger:
public function show(int $purchaseOrder)
{
dd(PurchaseOrder::find($purchaseOrder));
}
Then dd() dumps out what I expect ( the record in the database where the id matches $purchaseOrder)
However if instead I do this:
public function show(PurchaseOrder $purchaseOrder)
{
dd($purchaseOrder);
}
Then $purchaseOrder is an empty model and not populated with any data from the database. My route looks like this:
Route::get('purchase-orders/{purchase_orders}/show', ['as' => 'admin.purchase-orders.show', 'uses' => 'PurchaseOrdersController#show']);
This is code that I've inherited and I'm trying to update from Laravel 5.3 to Laravel 5.6. Where should I be looking to solve this issue of the model not being populated correctly?
The implicit model binding requires you to match the variable name with the route parameter name, so for example, for the following method:
public function show(PurchaseOrder $purchaseOrder)
{
dd($purchaseOrder);
}
The route should contain the matching parameter name, for example:
Route::get('purchase-orders/{purchaseOrder}/show', [
'as' => 'admin.purchase-orders.show',
'uses' => 'PurchaseOrdersController#show'
]);
Notice that, the method parameter name in show method which is $purchaseOrder and the route parameter name {purchaseOrder} both are same and that's a requirement for the implicit model binding, otherwise you have to do an explicit model binding, where you've to explicitly tell the framework about your parameter name, for example (in RouteServiceProvider):
public function boot()
{
parent::boot();
Route::model('purchase_orders', App\PurchaseOrder::class);
}
This will tell the framework that, if there is the {purchase_orders} parameter name available in the route then resolve/bind an instance of PurchaseOrder model into the given method for that route.

Laravel route conflict

I have two routes:
Route::get('subjects/{subject}/{tag?}', 'SubjectController#show');
Route::get('subjects/{subject}/{tag}/{lesson}','LessonController#show');
When I hit the first route, it works properly but when I hit the second route, I get the following error response:
Sorry, the page you are looking for could not be found.
Is this because laravel is trying to treat the /{tag}/{lesson} portion of 2nd route as the value of the parameter of 1st route?
My controller methods are as follows:
//SubjectController.php
public function show($subjectSlug, $tag = null)
{
dd('Inside SubjectController#show');
}
//LessonController.php
public function show(Subject $subject, Tag $tag, Lesson $lesson)
{
dd('Inside LessonController#show');
}
When I visit, say,
localhost:3000/subjects/mysubject-slug/1
It matches the first route and responds accordingly, but when I visit,
localhost:3000/subjects/mysubject-slug/1/mylesson-slug
it shows the page not found error. How can I fix this?
As mentioned in the comments, because of Route Model Binding you can end up with a 404 when the model for the binding can not be retrieved. When using implicit route model binding the primary key will be used to search against by default. This can be changed on the model to use a different field, in this case the slug field.
"If you would like model binding to use a database column other than id when retrieving a given model class, you may override the getRouteKeyName method on the Eloquent model"
Laravel 5.5 Docs - Routing - Route Model Binding - Implicit Binding
public function getRouteKeyName()
{
return 'slug';
}
Try to change your controller to
//LessonController.php
public function show($subject, $tag, $lesson)
{
dd('Inside LessonController#show');
}
And see if it gets hit. If it does, your binding is done incorrectly.
On the side note, I suppose you don't have Route::resource() set up somewhere up in the routes file?

Laravel 5.5 Resource Controller and Dependecy Injection

I am working on a Laravel 5.5 application. When I use php artisan make:model SomeModel -mr it creates the model, migration and resource controller.
I've been noticed that some methods have by default only one parameter: the model:
public function show(SomeModel $someModel)
{
...
}
If you look into the $someModel variable it has an empty SomeModel object.
I was reading on Laravel Documentation that it looks like the Containers or Facades but I am not sure how to use this. Do you?
Edit 1:
I had my routes defined in routes/web.php as: Route::resource('users', 'UserController');
Now I had to define all the routes manually since automatic binding was not working:
Route::get('users', 'UserController#index');
Route::get('users/create', 'UserController#create');
Route::post('users', 'UserController#store');
Route::get('users/{user}/edit', 'UserController#edit', function(App\User $user) {});
Route::post('users/{user}', 'UserController#update', function(App\User $user) {});
Route::post('users/{user}/delete', 'UserController#destroy', function(App\User $user) {});
So, should I replace every resource controller route to manual routing like this?
The resource controller is expecting you to use route model binding. In your routes file, each route that corresponds to a controller action with an injected model will need to have a matching parameter.
For example:
Route::get('user/{user}', 'UserController#show');
Using the above route, the following controller action would receive a user instances that corresponds to the user ID passed as a URL parameter.
class UserController extends Controller
{
public function show(User $user)
{
...
}
}
The reason you're seeing an empty model now is that Laravel will just pass and fresh model to the controller if it is not bound to a route parameter. In other words, if you forget to bind the model in your routes file automatic injection will just give you a new instance.
Note that if you are using a route resource the resulting routes should already have the correct parameters
Route::resource('users', 'UserController');
You can run php artisan route:list to confirm that your actual routes are correct.
Your problem is your controller is expecting two parameters like below:
public function show($id, User $user)
if you try:
public function show(User $user)
it should work correctly.
In your route you are passing only a single param like:
user/{user}
So if you dd the first param it will display the number 1 but if you pass that
to the model it will return the corresponding user as per what id you pass in the route.
The reason your User model was returning an empty object was because there was no value passed to it.
Also make sure your route placeholder: /{user} matches the variable name in
the controller: public function show(User $user).
Hope this helps.
I too came across with the same problem.
If your model having two or more words, you have to use only small letters like $modeModel as $somemodel.
public function show(SomeModel $somemodel)
{
...
}

Laravel 5.2 implicit route model binding using uuid string as id

I'm setting up a new laravel installation and have come to an issue with implicit route model binding when using a uuid as an id.
My route:
Route:group(['prefix' => 'admin'], function(){
Route:resource('users', 'Admin\UserController');
});
The show method of Admin\UserController:
public function show(App\User $user) {
dd($user);
}
So when I hit the URL my.app/admin/users/long-uuid-string-here I would expect to see the user information but I get an empty User object.
When I add the following to the RouteServiceProvider, it works as expected:
$router->model('admin/users', \App\User::class);
Is there something I am missing, does implicit model binding expect an integer? Is it because it is in a route group or something else?
Yes! the id exists in the database, and I am using laravel 5.2
Since you are using resource routing, the route will be like:
Route::get('admin/users/{users}', 'Admin\UserController#show');
Note the {users} variable. It's plural. So in your show method:
change this:
public function show(App\User $user) {
dd($user);
}
to
public function show(App\User $users) {
dd($users);
}
It's a bit weird, but thats the problem.

Categories