Laravel 控制器依赖注入
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42817496/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Laravel Controller Dependency Injection
提问by Summer Developer
I'm trying to do dependency injection in Laravel to keep my controllers and models as slim as possible. The goal is to have repositories to handle the fetching of data attributed to certain models.
我正在尝试在 Laravel 中进行依赖注入,以使我的控制器和模型尽可能地纤薄。目标是拥有存储库来处理归因于某些模型的数据的获取。
To this end I'm trying to follow the example from the documentation hereand a popular Laravel boilerplate here
But I don't understand where the $user
is coming from.
但我不明白它$user
是从哪里来的。
So looking at the boilerplate we have two files:
所以看看样板文件,我们有两个文件:
The ProfileController
here
在ProfileController
这里
Excerpt below:
摘录如下:
use App\Repositories\Frontend\Access\User\UserRepository;
/**
* Class ProfileController.
*/
class ProfileController extends Controller
{
/**
* @var UserRepository
*/
protected $user;
/**
* ProfileController constructor.
*
* @param UserRepository $user
*/
public function __construct(UserRepository $user)
{
$this->user = $user;
}
This looks a lot like the dependency injection mentioned in the docs, which is this:
这看起来很像文档中提到的依赖注入,它是这样的:
class UserController extends Controller {
/**
* The user repository instance.
*/
protected $users;
/**
* Create a new controller instance.
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
My problem is I don't understand where the $user
is coming from.
我的问题是我不明白$user
它来自哪里。
In the UserRepositorythere is no $user defined as a parameter of the class itself. No where in the code is there any Auth::user()
so I'm confused as to where the user instance is coming from.
在UserRepository 中,没有将 $user 定义为类本身的参数。代码中没有任何地方,Auth::user()
所以我对用户实例的来源感到困惑。
回答by jfadich
In Laravel dependency injection is handled by the Container. I'm simplifying, but you can think of the container as a source of objects. If there is a singleton, its stored in the container. Otherwise the container knows how to instantiate objects for you. Whenever Laravel calls a method (like in a controller) or instantiates an object for you it will inspect the constructor and look for type hinted dependencies. If it sees a dependency it knows how to retrieve or create it will do so and pass it in for you.
在 Laravel 中,依赖注入由Container处理。我正在简化,但您可以将容器视为对象的来源。如果有单例,则将其存储在容器中。否则容器知道如何为您实例化对象。每当 Laravel 调用一个方法(例如在控制器中)或为您实例化一个对象时,它都会检查构造函数并查找类型提示的依赖项。如果它看到一个依赖项,它知道如何检索或创建它会这样做并为您传递它。
So when Laravel instantiates the controller it looks at the constructor
所以当 Laravel 实例化控制器时,它会查看构造函数
public function __construct(UserRepository $user)
{
$this->user = $user;
}
The container uses Type Hinting to see that it requires a UserRepository
so it will instantiate a new one for you. It also does this recursively. So when it creates a new UserRepository
it looks at that constructor and sees that it requires a RoleRepository
so it will instantiate that as well.
容器使用 Type Hinting 来查看它需要一个,UserRepository
因此它会为您实例化一个新的。它也递归地执行此操作。因此,当它创建一个 new 时,它会UserRepository
查看该构造函数并发现它需要 a,RoleRepository
因此它也会实例化它。
TLDR: The service container inspects your dependencies and will instantiate them for you.
TLDR:服务容器会检查您的依赖项并为您实例化它们。
回答by S. Imp
Welcome to the dubious magic of Laravel. The basic idea with these dependency injections is that, depending on how you define your routes & controllers, Laravel can perform some automagical parsing of urls, identification of ids in those urls, and database fetching of objects.
欢迎来到 Laravel 的神秘魔法。这些依赖注入的基本思想是,根据你定义路由和控制器的方式,Laravel 可以执行一些 url 的自动解析、这些 url 中的 id 识别以及对象的数据库获取。
My problem is I don't understand where the $user is coming from.
我的问题是我不明白 $user 来自哪里。
You should probably read the docs on the service container. You can also get a better idea of how your route definitions translate into parameter-laden urls with this command:
您可能应该阅读有关服务容器的文档。您还可以使用以下命令更好地了解路由定义如何转换为包含参数的 url:
php artisan route:list
On one of my projects, this results in this output:
在我的一个项目中,这会产生以下输出:
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
| | GET|HEAD | / | | Closure | web |
| | GET|HEAD | api/user | | Closure | api,auth:api |
| | GET|HEAD | categories | categories.index | App\Http\Controllers\CategoryController@index | web |
| | POST | categories | categories.store | App\Http\Controllers\CategoryController@store | web |
| | GET|HEAD | categories/create | categories.create | App\Http\Controllers\CategoryController@create | web |
| | GET|HEAD | categories/{category} | categories.show | App\Http\Controllers\CategoryController@show | web |
| | PUT|PATCH | categories/{category} | categories.update | App\Http\Controllers\CategoryController@update | web |
| | DELETE | categories/{category} | categories.destroy | App\Http\Controllers\CategoryController@destroy | web |
| | GET|HEAD | categories/{category}/edit | categories.edit | App\Http\Controllers\CategoryController@edit | web |
| | GET|HEAD | products | products.index | App\Http\Controllers\ProductController@index | web |
| | POST | products | products.store | App\Http\Controllers\ProductController@store | web |
| | GET|HEAD | products/create | products.create | App\Http\Controllers\ProductController@create | web |
| | GET|HEAD | products/{product} | products.show | App\Http\Controllers\ProductController@show | web |
| | PUT|PATCH | products/{product} | products.update | App\Http\Controllers\ProductController@update | web |
| | DELETE | products/{product} | products.destroy | App\Http\Controllers\ProductController@destroy | web |
| | GET|HEAD | products/{product}/edit | products.edit | App\Http\Controllers\ProductController@edit | web |
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
And all those routes and their uris and parameters are generated from only a couple of very simple routes definitions. Here's my routes file:
所有这些路由及其 uri 和参数仅从几个非常简单的路由定义生成。这是我的路由文件:
$ cat routes/web.php
<?php
Route::get('/', function () {
return view('master');
});
Route::resource('products', 'ProductController');
Route::resource('categories', 'CategoryController');
If you look at the list of URIs in the routes output above, you'll see parameters named in the URIs like {category}and {product}. These correspond to ids/keys in the URI which Laravel identifies. Laravel is "smart" enough to look at my Controller files, see the type-hinting in the various functions and detect that my function is expecting a depedency to be injected.
如果您查看上面路由输出中的 URI 列表,您将看到在 URI 中命名的参数,如{category}和{product}。这些对应于 Laravel 标识的 URI 中的 ids/keys。Laravel 足够“聪明”,可以查看我的控制器文件,查看各种函数中的类型提示,并检测到我的函数期望注入依赖项。
For instance, the Category controller's showmethod looks like this:
例如,类别控制器的show方法如下所示:
public function show(Tree $category)
{
var_dump($category);
}
My controller might seem a little unusual because I'm type hinting that I want an object of type Tree, but Laravel is smart enough to recognize that I do in fact want a Model of type Tree, so it parses out the url and finds the id in it and automatically fetches the record in my db table treeswith id matching the {category} fragment of my url and injects that into my function.
我的控制器可能看起来有点不寻常,因为我的类型暗示我想要一个 Tree 类型的对象,但 Laravel 足够聪明,可以识别出我实际上想要一个 Tree 类型的模型,所以它解析出 url 并找到id 并自动获取我的数据库表树中的记录,其 id 与我的 url 的 {category} 片段匹配,并将其注入我的函数中。
Note that I had some troublewhen I tried to name the input parameter $tree instead of $category. That other thread may help answer your question a bit too.
请注意,当我尝试将输入参数命名为 $tree 而不是 $category 时遇到了一些麻烦。其他线程也可能有助于回答您的问题。
The bottom line is that Laravel does a lot of "magic" to hopefully free you up from the tedious of manually defining your own code and queries to retrieve the objects you want.
最重要的是,Laravel 做了很多“魔法”,希望让您免于手动定义自己的代码和查询以检索所需对象的繁琐。
回答by Mahedi Hasan Durjoy
You can follow this article. I hope you can clearly understand about dependency injection. Reference Understanding Constructor and Method Dependency Injection in Laravel
你可以关注这篇文章。我希望你能清楚地了解依赖注入。参考理解 Laravel 中的构造函数和方法依赖注入