简体   繁体   English

Laravel,依赖注入和Eloquent

[英]Laravel, Dependency Injection, and Eloquent

What the right/best way to use laravel's dependency injection system with multiple-instance objects like CRUD models? 使用laravel的依赖注入系统与CRUD模型等多实例对象的正确/最佳方法是什么?

Current fashion in some corners of PHP-land say the following code is "bad" PHP-land的某些角落目前的时尚说下面的代码是“坏的”

function someMethod()
{
    /* .. stuff ... */
    $object = new \App\SomeModel;
    $object->some_prop = 'some value';
    $object->save();
    /* .. other stuff ... */
}

It's bad because this method is now dependent on that new object instantiation. 这很糟糕,因为此方法现在依赖于新的对象实例化。 The current fashion says objects ought to be injected via some sort of dependency injection system, like Laravel's automatic constructor dependency injection . 目前的时尚说,对象应该通过某种依赖注入系统注入,比如Laravel的自动构造函数依赖注入

However -- injecting eloquent models seems problematic 然而 - 注入雄辩模型似乎存在问题

/*...*
public function __construct(\App\SomeModel $object)
{
    $this->someModel = $object;
}

function someMethod()
{
    /* .. stuff ... */
    $object = $this->someModel;
    $object->some_prop = 'some value';
    $object->save();
    /* .. other stuff ... */
}  
/*...*/           

It's not clear if Laravel's automatic constructor dependency injection creates new instances each time, or if the objects injected are single instance objects. 目前尚不清楚Laravel的自动构造函数依赖注入是否每次都创建新实例,或者注入的对象是否是单实例对象。 It also doesn't handle situations where you want to use Eloquent's static helpers 它也不处理您想要使用Eloquent的静态助手的情况

function someMethod($object_id)
{
    //another dependency
    \App\SomeModel::find($object_id);

    //but this doesn't work
    $this->someModel->find($object_id);
}    

Is there a generally accepted way to handle this in a Laravel application? 在Laravel应用程序中是否有一种普遍接受的方法来处理它? Some people say you should inject factories. 有人说你应该注入工厂。 Other people say repositories. 其他人说存储库。 I'd like to know what the general practice is with Laravel developers and if Laravel ships with anything that can help out here (base factory/repository implementations, etc.) 我想知道Laravel开发人员的一般做法是什么如果Laravel附带了任何可以帮助的东西(基础工厂/存储库实现等)

Thanks to some help from the LaraChat Slack I figured this one out on my own. 感谢LaraChat Slack的一些帮助,我自己想出了这个。

It turns out that, in addition to automatic constructor dependency injection, Laravel has a special form of dependency injection that works with any of a router's callback methods/functions . 事实证明,除了自动构造函数依赖注入之外,Laravel还有一种特殊形式的依赖注入,可以与任何 路由器的回调方法/函数一起使用

Consider this code sample 考虑这个代码示例

Route::get('api/users/{user?}', function (App\User $user) {
    return $user->email;
});

If you setup your route string with a variable ( {user} ), Laravel will scan your route handler's (above, an anonymous function, but it works with controller methods as well) parameters for a type hint whose short class name matches the variable name ( App\\User above). 如果使用变量( {user} )设置路径字符串,Laravel将扫描您的路由处理程序(上面是一个匿名函数,但它也适用于控制器方法)参数,用于类型提示,其短类名称与变量名称匹配(上面的App\\User )。 If found, instead of passing in the parameter from URL, Laravel will instantiate a loaded Eloquent object. 如果找到,则Laravel将实例化一个已加载的 Eloquent对象,而不是从URL传入参数。 If an optional parameter is ommited, you'll get a blank object of the specified type. 如果省略了可选参数,您将获得指定类型的空白对象。

This extensive discussion of Laravel DI is great. 对Laravel DI的广泛讨论很棒。 Covers the use of classes and interfaces and more. 涵盖了类和接口的使用等。 Best reference I've found. 我发现最好的参考。 https://gist.github.com/davejamesmiller/bd857d9b0ac895df7604dd2e63b23afe https://gist.github.com/davejamesmiller/bd857d9b0ac895df7604dd2e63b23afe

Laravel has a powerful Inversion of Control (IoC) / Dependency Injection (DI) Container. Laravel具有强大的控制反转(IoC)/依赖注入(DI)容器。 Unfortunately the official documentation doesn't cover all of the available functionality, so I decided to experiment with it and document it for myself. 不幸的是,官方文档并未涵盖所有可用功能,因此我决定对其进行试验并自行记录。 The following is based on Laravel 5.4.26 - other versions may vary. 以下是基于Laravel 5.4.26 - 其他版本可能有所不同。

I had a bit of a play with this (no serious testing) and it looks like it's possible - in fact, I rather like it doing it this way, and look to it in the future. 我有一点玩这个(没有严肃的测试),看起来它是可能的 - 事实上,我更喜欢它这样做,并期待在未来。 Sample (untested) below: 样品(未经测试)如下:

use App/Models/Foo;

class FooController {

    private $model;

    public function __construct(Foo $model) 
    {
       $this->model = $model;
    }

    public function show(Request $request, $id)
    {
        $foo = $this->model->where($this->model->getKeyName(), '=', $id)->first();

        dd($foo);
    }

    public function store(Request $request)
    {
        $foo = $this->model->newInstance();
        $foo->bar = $request->get('baz');
        $foo->save();
    }

}

The find helpers that are on the eloquent facades, such as find, are nice, but essentially under the hood they are a standard where(...)->get()->first(). 雄辩的外观上的查找助手,比如find,很不错,但基本上它们是标准的(...) - > get() - > first()。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM