Failed Laravel dependency injection in controller method - php

I have a model called Dbtable which isn't injected when used like this:
public function showEditDbTableForm(Request $request, DbTable $table)
{
}
it only works when I do this:
public function showEditDbTableForm(Request $request, $id)
{
$table = DbTable::find( $id );
}
Same thing happens even when I rename DbTable to DbTble
P.S.: please don't be rude with me as I'm new to Laravel framework

For Implicit Route Model Binding you need to make sure the parameter in the method signature has the same name as the route parameter you want to bind.
Route::get('widgets/{widget}', 'WidgetsController#show');
public function show(Widget $widget)
Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name.
Laravel 5.6 Docs - Routing - Implicit Model Binding

In RouteServiceProvider class add
public function boot()
{
parent::boot();
Route::model('db-table', App\DbTable::class);
// db-table correspond your rout parameter
}
see official documentation https://laravel.com/docs/5.5/routing Explicit Binding section

Related

Laravel boilerplate send object to controller

I am newbie with Laravel. I have just fork laravel 5 boilerplate from https://github.com/rappasoft/laravel-5-boilerplate.
In route files, i see that there is a line like that :
Route::group(['prefix' => 'user/{deletedUser}'], function () {
Route::get('delete', 'UserStatusController#delete')->name('user.delete-permanently');
Route::get('restore', 'UserStatusController#restore')->name('user.restore');
});
I understand it means that, when url catch 'restore' it will use function restore in UserStatusController.
And here it is:
public function restore(User $deletedUser, ManageUserRequest $request)
Can anybody can help me to find out that, how can it send object $deletedUser to restore function. Tks you!
If your look at the route definition:
user/{deletedUser}
That {deletedUser} represents the id of the user to be deleted/restored. Variables are declared between {} in routes as the docs states.
Now in your controller:
public function restore(User $deletedUser, ManageUserRequest $request)
You can see that a User object is declared as an argument. This object is being injected by Laravel, that automatically will look for an User object that has that id. This is called Route Model Binding.
The documentation explains it better:
When injecting a model ID to a route or controller action, you will often query to retrieve the model that corresponds to that ID. Laravel route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire User model instance that matches the given ID.
The same way, the Request class injected in this case is a ManageUserRequest that should be an instance of a FormRequest.
So, returning to your question, you will just have to specify the user id that you want to delete/restore, like this:
someurl.dev/users/5 // <-- for the user of id=5
Now your controller will interact with that specific object to do what you want:
public function restore(User $deletedUser, ManageUserRequest $request)
{
$deletedUser->delete(); // for example
}
There are two things happening here: parameters (docs) and model binding (docs)
First of all, in ['prefix' => 'user/{deletedUser}'] you can see that you are parsing a parameter from the url. This way, when someone navigates to api/user/3, laravel will pass the 3 to your route handler.
Second, it would be very nice to get the User model instance instead of just getting an id number. That's possible and it's called "model binding". Model binding can be
Explicit
You add your bindings to boot method in your RouteServiceProvider class, telling laravel what is the expected type of parameter.
public function boot()
{
parent::boot();
Route::model('deletedUser', App\User::class);
// in older docs I've seen 'App\User' passed as a string instead of as a class
}
Implicit
Laravel automatically figures out what model you need based on type hints.
public function restore(User $deletedUser, ManageUserRequest $request) {}
Here, $deletedUser has is type hinted as User. Laravel sees this, so it will go ahead and convert the id to the Eloquent model for you.
You seem to be using implicit binding, but feel free to check your RouteServiceProvider class.
Check the documentation links for more details, it's pretty well written. (If you are not using version 5.6, then just change the version number in the links).
You Just need to pass ID of the user as a parameter.
And this function
public function restore(User $deletedUser, ManageUserRequest $request)
you can see $deletedUser is of type User Laravel will search for that id ($deletedUser) in Users table and return an object of that user.
If you don't want User object and just need ID that you are passing in URL update restore() function to
public function restore($deletedUser, ManageUserRequest $request)

Laravel Eloquent: route model binding not working with multi word table name

i'm making a delete call with ajax to my destroy route for a model.
Everything works, except that the controller doesn't match the corresponding record in the database.
I call a api/serviceoperations/17 ajax delete call, but if i place a var_dump in my controller in this way:
public function destroy(ServiceOperation $serviceOperation) {
var_dump($serviceOperation);die;
}
i get an empty model that doesn't exists
public 'exists' => boolean false
Of course I have a model called ServiceOperation that refers to the table service_operations, with the primary key id, and in my database there's a record with key 17.
Why doesn't the controller resolves my id the route to the relative record in the db?
update (solved):
Model, Controller and Migration were created with the command
php artisan make:model -m -c -r App\Models\ServiceOperation
Anyway it seems that laravel doesn't hand very well table's name with more then one world:
While the command above works good with one word table name (ie App\Model\Service), it doesn't works with 2 or more, since it wouldn't bind by itself the model passed in the route.
The solution is to use the input variable name in controller with all lowercase character.
In my case, the auto generated destroy function in controller was
public function destroy(ServiceOperation $serviceOperation) {
//model bind not working
}
But the model bind wasn't working.
Updating the parameter to a lowercase string, solve the issue, and model bind works:
public function destroy(ServiceOperation $serviceoperation) {
//model bind working
}
The solution is to use the input variable name in controller with all lowercase character.
In my case, the auto generated destroy function in controller was
public function destroy(ServiceOperation $serviceOperation) {
//model bind not working
}
But the model bind wasn't working.
Updating the parameter to a lowercase string, solve the issue, and model bind works:
public function destroy(ServiceOperation $serviceoperation) {
//model bind working
}
the problem is in the wild card provided in the route file
Route::get('/serviceoperation/{wildcard}', 'PostsController#destroy');
the {wildcard} has to match in your controller
public function destroy(ServiceOperation $wildcard) {
//model bind working
}
as long as this too names match, the model binding will work as long as the wildcard is the id
You can solve it with this thing -> Laravel explicit bindings.
You can make explicit bindings in the RouteServiceProvider boot method like this:
/**
* Define your route model bindings, pattern filters, etc.
*
* #return void
*/
public function boot()
{
parent::boot();
Route::model('ServiceOperation', \App\ServiceOperation::class);
}
Try this:
public function destroy(ServiceOperation $serviceOperation, $id) {
$resource = $serviceOperation->find($id);
return $resource->delete();
}
See, if that helps.

How to make Generic Route in Laravel 4

How can I make a router like this
Route::any("/{controller}/{method}/{param}", "$controller#$method");
So that instead of specifing every single method in the routes file, I would be able to define a route for most cases for the convention http://example.com/controller/method/param
In Laravel 4.2 you can use [implicit controller][1].
Laravel allows you to easily define a single route to handle every action in a controller. First, define the route using the Route::controller method:
Route::controller('users', 'UserController');
The controller method accepts two arguments. The first is the base URI the controller handles, while the second is the class name of the controller. Next, just add methods to your controller, prefixed with the HTTP verb they respond to:
class UserController extends BaseController {
public function getIndex()
{
//
}
public function postProfile()
{
//
}
}
https://laravel.com/docs/4.2/controllers#implicit-controllers
Like this:
Route::any('{controller}/{method}/{param}', function ($controller, $method, $param) {
return call_user_func_array($controller.'::'.$method, $param);
});

laravel5 generate routes key

i use laravel 5.2 now.
i have these codes in my routes.php file:
Route::(['dashboard'=>'DashboardArticelController',]);
and laravel generates some router for my app :
GET /dashboard/my-articles App\Http\Controllers\DashboardArticelController#getMyArticles
here is a method in my controller:
public function getMyArticles()
{
//$articels = Auth::user()->articals()->latest('published_at')->get();
//dd(Auth::user()->articals()->latest('published_at')->simplePaginate(3));
$articels = Auth::user()->articals()->latest('published_at')->Paginate(5);
return view('dashboard.view.dashboardArticelEdit',compact('articels'));
}
i wonder how the laravel5 generates this route ,i can not found the method can generates the route with the method name.
By default, Laravel assumes an Eloquent model should map to URL segments using its id column. But what if you expect it to always map to a slug?
Eloquent implements the Illuminate\Contracts\Routing\UrlRoutable contract, which means every Eloquent object has a getRouteKeyName() method on it that defines which column should be used to look it up from a URL. By default this is set to id, but you can override that on any Eloquent model:
class Test extends Model
{
public function getRouteKeyName()
{
return 'slug';
}
}

Route model binding and parent child validation in Laravel

Say I have a route like:
Route::get('users/{user}/posts/{post}', 'PostController#show')
And I've set up Route Model binding for an App\User to {user} and an App\Post to {post}. I've seen I'm able to call whatever existing post for any given user to get contents on the screen. Is there a generic place where I can assign constraints to the bound models?
you can use Route::bind and set a second variable for the function to access the current route and it parameters like this:
class RouteServiceProvider extends ServiceProvider{
public function boot(Router $router)
{
$router->bind('user', function($value) {
return App\User::findOrFail($value);
});
$router->bind('post', function($value, $route) {
return $route->parameter('user')->posts()->findOrFail($value);
});
}
}
You can use $router->bind() to control how a model is fetched:
Route::get('/user/{name}', 'PostController#show');
$router->bind('user', function($value) {
return App\User::where('name', $value)->first();
});
This certainly is a gap in laravel. I made a little package to help.
https://github.com/tarekadam/laravel-orm-binding-validation
Use middleware not validation.
Append the middleware so that binding already ran.
Define the expected relationships in the controller.
See README.md on the package.

Categories