2

我的团队喜欢构造函数注入依赖项的想法,因为它使 deps 在查看类时非常清晰。通过使用外观,我知道它们可以被嘲笑和swapped,但是必须检查类的每一行才能弄清楚它依赖于什么!我发现我可以在外观后面找到真正的类,例如Form::getFacadeRoot().

我最终得到的控制器代码是:

use Illuminate\Html\FormBuilder as Form;
use Illuminate\Validation\Factory as Validator;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage as Session;
use Illuminate\Http\Request as Input;
use Illuminate\Routing\Redirector as Redirect;
use Illuminate\View\Environment as View;

class HomeController extends BaseController {

    protected $form;
    protected $validator;
    protected $session;
    protected $input;
    protected $redirect;
    protected $view;

    protected $layout = 'layouts.master';

    protected $validationRules = array(
        'name'  => array('required', 'min:3'),
        'email' => array('required', 'regex:/^.+@.+\..{2,4}$/')
    );

    public function __construct(Form $form, Validator $validator, Session $session,
        Input $input, Redirector $redirect, View $view
    ) {
        $this->form      = $form;
        $this->validator = $validator;
        $this->session   = $session;
        $this->input     = $input;
        $this->redirect  = $redirect;
        $this->view      = $view;
    }

        ...
}

当我的测试执行$this->client->request('Get', '/');时,它会出错:

Illuminate\Container\BindingResolutionException: Unresolvable dependency resolving [Parameter #2 [ <required> $csrfToken ]].

我在这里甚至接近正确的轨道吗?我正在编造这个,因为我没有看到太多关于这个问题的讨论。随意评论我尝试的理由;我可以在外墙出售,但是。

谢谢 !

4

2 回答 2

7

您需要使用 Laravel 的 IoC 容器将类依赖项映射到一个类。这可以使用 App 外观来完成。所以在你上面的例子中,构造函数

public function __construct(Form $form, Validator $validator, Session $session, Input $input, Redirector $redirect, View $view)

您将创建一个看起来类似于以下内容的绑定:

App::bind('Form', function(){
    return new Illuminate\Html\FormBuilder()
});

Taylor Otwell 建议使用接口作为类依赖的契约。所以理想情况下,你完成的代码看起来像下面的样子(我已经把它缩小了一点)。

对于您的控制器:

use Namespace\For\FormInterface;

class HomeController extends BaseController {

    public function __construct(FormInterface $form)
    {
        $this->form = $form;
    }

    public function myHomePage()
    {
        $this->form->myFormFunction()
    }
}

对于接口:

namespace Namespace\For;

interface FormInterface(){

    public function myFormFunction()
}

要注入的类:

use Namespace\For\FormInterface;

class MyFormClass implements FormInterface{

    public function myFormFunction()
    {
        // Do some stuff here
    }
}

最后,您创建了将它们组合在一起的绑定:

App::bind('Namespace\For\FormInterface', function()
{
    return new MyFormClass();
});

这里发生的情况是每次 Laravel 看到FormInterface控制器中提示的类型实例 if 创建一个新的myFormFunction()并将其作为参数传递。通过使用接口,它为您的类依赖项提供了一个可以遵循的契约,以确保它们可以轻松交换而不会导致错误。因此,假设您的团队稍后开发了一个新的和改进的表单类,您只需像这样更新您的绑定:

App::bind('Namespace\For\FormInterface', function()
{
    return new  MyNewFormClass();
});

我强烈建议研究服务提供者,因为它们提供了一种管理包和 IoC 绑定的极好方法。可以在这里找到一篇关于服务提供者的好文章:

http://fideloper.com/laravel-4-where-to-put-bindings

你可以在这里阅读更多关于 Laravel 的 IoC 容器的信息:

http://laravel.com/docs/ioc

此外,如果你能拿到一本从学徒到工匠的书。使用 Laravel 4 的高级应用程序架构,作者 Taylor Otwell 我强烈推荐阅读。它易于理解,并且非常详细地介绍了管理依赖注入。

希望有帮助。

于 2013-10-12T09:04:43.883 回答
2

如果你选择这条路线,我认为你会在可读性上牺牲很多。

最终,依赖注入只是一种允许可测试性的模式。无需注入即可轻松测试外墙,因此我认为这样做没有太大价值...

于 2013-06-10T20:52:22.313 回答