我的团队喜欢构造函数注入依赖项的想法,因为它在查看类时非常清楚deps。随着外墙的使用,我知道他们可以被嘲笑和swap
ped,但是人们必须检查一个类的每一行以找出它依赖的东西!我发现我可以在幕后找到真正的类,例如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 ]].
我是否接近正确的轨道?我有点像这样做,因为我没有看到很多关于这个问题的讨论。随意评论我尝试的原因;我可以在外墙上出售。
谢谢!
答案 0 :(得分:7)
您需要使用Laravel的IoC容器将类依赖关系映射到类。这可以使用App facade完成。所以在上面的示例中使用构造函数
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建议使用Interfaces作为类依赖关系的契约。因此,理想情况下,您完成的代码看起来就像下面的内容(我已经将它简化了一点)。
对于您的控制器:
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
类型的实例在控制器中暗示如果创建一个新的myFormFunction()
并将其作为参数传递。通过使用接口,它为您的类依赖项提供了遵循的契约,以确保它们可以轻松交换而不会导致错误。所以说你的团队后来开发了一个新的改进的表单类,你只需更新你的绑定:
App::bind('Namespace\For\FormInterface', function()
{
return new MyNewFormClass();
});
我强烈建议您查看服务提供商,因为它们提供了管理包和IoC绑定的绝佳方法。有关服务提供商的文章可以在这里找到:
http://fideloper.com/laravel-4-where-to-put-bindings
您可以在此处阅读有关Laravel的IoC容器的更多信息:
此外,如果您可以获得从Apprentice到Artisan的书的副本。高级应用程序架构使用Laravel 4,Taylor Otwell我强烈推荐阅读。它很容易理解并且真正详细地介绍了如何管理依赖注入。
希望有所帮助。
答案 1 :(得分:2)
如果你选择这条路线,我认为你会牺牲很多可读性。
最终,依赖注入只是一种允许可测试性的模式。外立面在没有注射的情况下很容易测试,所以我认为这样做没有多大价值......