2017-03-15 202 views
3

我试图在Laravel中执行依赖注入以使我的控制器和模型尽可能地保持苗条。目标是让存储库处理提取归因于某些模型的数据。Laravel控制器依赖注入

为此我试图从文档here和流行Laravel样板here

效仿的榜样,但我不明白的地方的$user的来源。

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

ProfileControllerhere

摘录如下:

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

'$ user'只是变量的名称。它也可以是'$ biggieSmalls'或其他任何东西。该变量只保存“UserRepository”的一个实例。 – devk

+0

Laravel的DIC创建它,因为控制器需要一个。 – bassxzero

+0

@devk该实例分配给该变量的位置在哪里?我知道它可以被命名为任何东西,但我不明白它在哪里分配。它不是在类型暗示是吗? –

回答

5

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

所以当Laravel实例化控制器,它看起来在构造

public function __construct(UserRepository $user) 
{ 
    $this->user = $user; 
} 

容器使用类型提示看,它需要一个UserRepository所以它将实例为你一个新的。它也递归地做到这一点。因此,当它创建一个新的UserRepository时,它会查看该构造函数,并发现它需要RoleRepository,因此它也会实例化该构造函数。

TLDR:服务容器检查您的依赖关系,并将为您实例化它们。

+0

好吧,这是有道理的。然后看起来Repository会根据传递的电子邮件判断哪个用户是基于它的,不明白为什么它不会使用'Auth :: user();'但是我想这是我的下一个任务!谢谢:) –

+0

如何注入需要使用setters配置的类。是否有与zend框架2.4相同的工厂模式?谢谢 – xiarnousx

+0

@xiarnousx我对Zend Framework并不熟悉,所以我不确定它是如何比较的,但是你可以通过[绑定到容器]定义一个对象应该如何构造(https://laravel.com/docs/ 5.5/container#binding-basics)然后,Laravel将使用该闭包在您请求注入时创建该对象。 – jfadich

2

欢迎来到Laravel的可疑魔法。这些依赖注入的基本思想是,根据您如何定义路由控制器,Laravel可以执行一些URL自动分析,标识这些URL中的ID以及获取对象的数据库。

我的问题是我不明白$用户来自哪里。

您应该读取docs on the service container。你也可以得到你的路由定义如何转化为参数载货网址,使用此命令一个更好的主意:

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\[email protected] | web   | 
|  | POST  | categories     | categories.store | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/create   | categories.create | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/{category}  | categories.show | App\Http\Controllers\[email protected] | web   | 
|  | PUT|PATCH | categories/{category}  | categories.update | App\Http\Controllers\[email protected] | web   | 
|  | DELETE | categories/{category}  | categories.destroy | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | categories/{category}/edit | categories.edit | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products     | products.index  | App\Http\Controllers\[email protected] | web   | 
|  | POST  | products     | products.store  | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/create   | products.create | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/{product}   | products.show  | App\Http\Controllers\[email protected]  | web   | 
|  | PUT|PATCH | products/{product}   | products.update | App\Http\Controllers\[email protected] | web   | 
|  | DELETE | products/{product}   | products.destroy | App\Http\Controllers\[email protected] | web   | 
|  | GET|HEAD | products/{product}/edit | products.edit  | App\Http\Controllers\[email protected]  | web   | 
+--------+-----------+----------------------------+--------------------+-------------------------------------------------+--------------+ 

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

$ cat routes/web.php 
<?php 

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

Route::resource('products', 'ProductController'); 
Route::resource('categories', 'CategoryController'); 

如果你看的URI的路由输出列表的上方,你会看到和{}产品中的URI命名为喜欢{}类参数。这些对应于Laravel标识的URI中的id/keys。 Laravel是“聪明的”,足以查看我的控制器文件,查看各种函数中的类型提示,并检测到我的函数正期望注入依赖。

例如,分类控制器的方法是这样的:

public function show(Tree $category) 
{ 
    var_dump($category); 
} 

,因为我,我想类型树的对象类型提示我的控制器似乎有点不寻常,但Laravel是足够聪明地认识到我确实需要一个类型树模型,所以它解析出url并找到它的id并自动获取我的db表中的记录,其ID与我的{category}片段匹配网址并注入到我的功能。

请注意,我试图命名输入参数$ tree而不是$ category时,我输入了had some trouble。那另一个线程可能有助于回答你的问题。

底线是,Laravel做了很多“魔术”,希望能够让你从繁琐的手动定义自己的代码和查询来检索你想要的对象。