我正在尝试在Laravel中进行依赖注入,以使我的控制器和模型尽可能保持苗条。目标是使用存储库来处理归因于某些模型的数据的获取。
为此,我尝试按照文档 here 和流行的Laravel样板 here
进行操作。但我不明白$user
的来源。
所以看看样板文件,我们有两个文件:
ProfileController
here
摘录如下:
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;
}
这看起来很像文档中提到的依赖注入,这就是:
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;
}
我的问题是我不明白$user
的来源。
在 UserRepository 中,没有将$ user定义为类本身的参数。没有代码中的任何地方Auth::user()
所以我对用户实例的来源感到困惑。
答案 0 :(得分:13)
在Laravel中,依赖注入由Container处理。我简化了,但您可以将容器视为对象的来源。如果有单例,则将其存储在容器中。否则,容器知道如何为您实例化对象。每当Laravel调用一个方法(比如在控制器中)或为你实例化一个对象时,它将检查构造函数并查找类型暗示的依赖项。如果它看到依赖关系,它知道如何检索或创建它将会这样做并将其传递给你。
因此,当Laravel实例化控制器时,它会查看构造函数
public function __construct(UserRepository $user)
{
$this->user = $user;
}
容器使用Type Hinting来查看它需要UserRepository
,因此它会为您实例化一个新的。它也递归地执行此操作。因此,当它创建一个新的UserRepository
时,它会查看该构造函数并发现它需要一个RoleRepository
,因此它也会实例化它。
TLDR:服务容器检查您的依赖项并为您实例化它们。
答案 1 :(得分:6)
欢迎来到Laravel的可疑魔力。这些依赖注入的基本思想是,根据您定义路线的方式而定。控制器,Laravel可以执行一些自动解析URL,识别这些URL中的ID,以及数据库提取对象。
我的问题是我不明白$用户来自哪里。
您应该阅读docs on the service container。您还可以使用此命令更好地了解路径定义如何转换为带参数的URL:
php artisan route:list
在我的一个项目中,这会产生以下结果:
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
| 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 |
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
所有这些路线及其uris和参数都是从几个非常简单的路线定义生成的。这是我的路线档案:
$ cat routes/web.php
<?php
Route::get('/', function () {
return view('master');
});
Route::resource('products', 'ProductController');
Route::resource('categories', 'CategoryController');
如果您查看上面路线输出中的URI列表,您会看到URI中指定的参数,例如 {category} 和 {product} 。这些对应于Laravel标识的URI中的ids /键。 Laravel是&#34; smart&#34;足以查看我的Controller文件,查看各种函数中的类型提示,并检测我的函数是否期望注入依赖项。
例如,类别控制器的显示方法如下所示:
public function show(Tree $category)
{
var_dump($category);
}
我的控制器看起来有点不寻常,因为我提示我想要一个Tree类型的对象,但是Laravel很聪明地认识到我确实想要一个Tree类型的模型,所以它解析出来url并在其中查找id并自动获取我的db表树中的记录,其id与我的url的{category}片段匹配,并将其注入我的函数。
当我尝试命名输入参数$ tree而不是$ category时,请注意我had some trouble。另一个主题也可能有助于回答你的问题。
最重要的是,Laravel做了很多&#34;魔术&#34;希望能让您摆脱手动定义自己的代码和查询以检索所需对象的繁琐工作。
答案 2 :(得分:0)
您可以关注本文。希望您能清楚了解依赖注入。 参考Understanding Constructor and Method Dependency Injection in Laravel