Laravel控制器依赖注入

Sum*_*per 11 php laravel laravel-5

我正在尝试在Laravel中进行依赖注入,以使我的控制器和模型尽可能保持苗条.目标是使存储库处理归因于某些模型的数据的获取.

为此我试图从文档效仿这里和受欢迎的Laravel样板这里

但我不明白它的$user来源.

所以看看样板文件我们有两个文件:

ProfileController 这里

摘录如下:

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;
    }
Run Code Online (Sandbox Code Playgroud)

这看起来很像文档中提到的依赖注入,这是:

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;
        }
Run Code Online (Sandbox Code Playgroud)

我的问题是我不明白它的$user来源.

UserRepository中,没有$ user被定义为类本身的参数.没有代码中的任何位置,Auth::user()所以我对用户实例的来源感到困惑.

jfa*_*ich 13

在Laravel中,依赖注入由Container处理.我正在简化,但您可以将容器视为对象的来源.如果有单例,则将其存储在容器中.否则,容器知道如何为您实例化对象.每当Laravel调用一个方法(比如在控制器中)或为你实例化一个对象时,它将检查构造函数并查找类型暗示的依赖项.如果它看到一个依赖项,它知道如何检索或创建它将这样做并传递给你.

因此,当Laravel实例化控制器时,它会查看构造函数

public function __construct(UserRepository $user)
{
    $this->user = $user;
}
Run Code Online (Sandbox Code Playgroud)

容器使用Type Hinting来查看它需要一个,UserRepository因此它将为您实例化一个新的.它也递归地执行此操作.因此,当它创建一个新的时,它会UserRepository查看该构造函数并发现它需要一个,RoleRepository因此它也将实例化它.

TLDR:服务容器检查您的依赖项并为您实例化它们.


S. *_*Imp 7

欢迎来到Laravel的可疑魔力.这些依赖注入的基本思想是,根据您定义路由和控制器的方式,Laravel可以执行一些URL的自动解析,这些URL中ID的识别以及对象的数据库提取.

我的问题是我不明白$ user的来源.

您应该阅读服务容器上的文档.您还可以使用此命令更好地了解路径定义如何转换为带参数的URL:

php artisan route:list
Run Code Online (Sandbox Code Playgroud)

在我的一个项目中,这会产生以下结果:

+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
| 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          |
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+
Run Code Online (Sandbox Code Playgroud)

并且所有这些路线及其uris和参数仅从几个非常简单的路线定义生成.这是我的路线文件:

$ cat routes/web.php
<?php

Route::get('/', function () {
    return view('master');
});

Route::resource('products', 'ProductController');
Route::resource('categories', 'CategoryController');
Run Code Online (Sandbox Code Playgroud)

如果查看上面路由输出中的URI列表,您将看到URI中指定的参数,如{category}{product}.这些对应于Laravel标识的URI中的ids /键.Laravel"智能"足以查看我的Controller文件,查看各种函数中的类型提示并检测我的函数是否期望注入依赖.

例如,类别控制器的show方法如下所示:

public function show(Tree $category)
{
    var_dump($category);
}
Run Code Online (Sandbox Code Playgroud)

我的控制器可能看起来有点不寻常,因为我提示我想要一个Tree类型的对象,但是Laravel足够聪明地认识到我确实想要一个Tree类型的Model,所以它解析出url并找到了id在其中并自动获取我的db表树中的记录,其id与我的url的{category}片段匹配,并将其注入我的函数中.

请注意,当我尝试命名输入参数$ tree而不是$ category时,我遇到了一些麻烦.那个其他线程也可能有助于回答你的问题.

最重要的是,Laravel做了很多"魔术",希望能让你摆脱手动定义自己的代码和查询以检索所需对象的繁琐工作.