我在Laravel项目中使用了Repository模式。 除了此代码段之外,官方文档中没有真正解释此模式:
您可以在控制器的构造函数中键入提示由应用程序定义的存储库。 存储库将自动解析并注入到类中。
这是我的代码,根据文档:
class CategoriesController extends Controller { protected $repo; public function __construct(CategoriesRepository $repo) { $this->repo = $repo; }我已经打字提示了CategoriesRepository,因此服务容器会自动加载它。
但是,如果我直接创建CategoriesController类的新实例(不使用服务容器),我必须指定我还需要CategoriesRepository的新实例,如下所示:
$example = new CategoriesController(new CategoriesRepository());现在,让我们假设我编写以下代码。
class CategoriesController extends Controller { protected $repo; public function __construct() { $this->repo = new CategoriesRepository(); }这样,我不必通过服务容器加载类,也不必通过传递CategoriesRepository的新实例作为参数来调用它,因为它是在构造函数内自动创建的。
所以,我的问题是:这是不好的做法吗? 类型提示作为参数和在构造函数内部创建新实例之间有什么区别?
I'm using a Repository pattern in my Laravel project. This pattern is not really explained in the official documentation, except for this snippet:
You may type-hint a repository defined by your application in a controller's constructor. The repository will automatically be resolved and injected into the class.
This is my code, in accordance with the documentation:
class CategoriesController extends Controller { protected $repo; public function __construct(CategoriesRepository $repo) { $this->repo = $repo; }I've type-hinted the CategoriesRepository so it gets automatically loaded by the Service Container.
However, if I directly create a new instance of the CategoriesController class (without using the Service Container), I have to specify that I need a new instance of the CategoriesRepository too, like this:
$example = new CategoriesController(new CategoriesRepository());Now, let's suppose I write the following code.
class CategoriesController extends Controller { protected $repo; public function __construct() { $this->repo = new CategoriesRepository(); }This way, I don't have to load the class through the Service Container, nor call it by passing a new instance of CategoriesRepository as the argument, because it's automatically created inside of the constructor.
So, my question is: would this be bad practice? What's the difference between type-hinting as a parameter and creating a new instance inside of the constructor?
最满意答案
这是依赖注入的美妙之处:
复杂初始化
class MyController { public function __construct(A $a) { } } class A { public function __construct(B $b) { } } class B { public function __construct(C $c) { } } class C { public function __construct(D $d) { } } class D { public function __construct() { } }现在您可以请求laravel为您创建该类,例如:
$controller = make(MyController::class);或者你可以这样做:
$controller = new MyController(new A(new B(new C(new D())))));此外,您可以指定有关如何创建变量的更复杂的规则:
app()->bind(D::class, function ($app) { $d = new D(); $d->setValueOfSomething($app->make(AnotherClass::class)); return $d; });测试
这是依赖注入优于手动创建事物的一个优点。 另一个是单元测试:
public function testSomeFunctionOfC() { $this->app->bind(D::class, function () { $dMock = $this->createMock(D::class); }); $c = make(C::class); }现在,当您创建C时,类D将是模拟类,您可以根据您的规范确保工作。
Here's the beauty of dependency injection:
Complex initialization
class MyController { public function __construct(A $a) { } } class A { public function __construct(B $b) { } } class B { public function __construct(C $c) { } } class C { public function __construct(D $d) { } } class D { public function __construct() { } }Now you can ask laravel to create that class for you e.g:
$controller = make(MyController::class);or you can do:
$controller = new MyController(new A(new B(new C(new D())))));In addition you can specify more complex rules on how to create the variables:
app()->bind(D::class, function ($app) { $d = new D(); $d->setValueOfSomething($app->make(AnotherClass::class)); return $d; });Testing
That's one advantage of dependency injection over manual creation of things. Another is unit testing:
public function testSomeFunctionOfC() { $this->app->bind(D::class, function () { $dMock = $this->createMock(D::class); }); $c = make(C::class); }Now when you create C the class D will be the mocked class instead which you can ensure works according to your specification.
更多推荐
发布评论