Luk*_*een 5 php phpunit unit-testing laravel laravel-4
我一直在改变我的控制器和辅助类以使用依赖注入,似乎我的助手类被卡在无限循环中.
下面是我的自定义ServiceProvider和两个示例助手类.正如你所看到的,他们互相注入,所以他们不停地来回走动.
这个问题的解决方案是什么?我似乎犯了什么错误?我能做些什么,这样我可以运行于辅助类,如测试General和Person,而嘲笑那些从他们内部叫助手类?
我认为可行的一种方法是在我的ServiceProvider中,执行以下操作:
if (isset($appmade->General)) {
// inject the General app that's already instantiated
} else {
$abc = app::make('\Lib\MyOrg\General');
$appmade->General = $abc;
}
Run Code Online (Sandbox Code Playgroud)
这是正确的方法吗?
// /app/providers/myorg/MyOrgServiceProvider.php
namespace MyOrg\ServiceProvider;
use Illuminate\Support\ServiceProvider;
class MyOrgServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('\Lib\MyOrg\General', function ($app) {
return new \Lib\MyOrg\General(
$app->make('\Lib\MyOrg\Person'),
$app->make('\App\Models\User')
);
});
$this->app->bind('\Lib\MyOrg\Person', function ($app) {
return new \Lib\MyOrg\Person(
$app->make('\Lib\MyOrg\General'),
$app->make('\App\Models\Device')
);
});
}
}
// /app/libraries/myorg/general.php
namespace Lib\MyOrg;
use App\Models\User;
use Lib\MyOrg\Person;
class General
{
protected $model;
protected $class;
public function __construct(Person $personclass, User $user)
{
}
}
// /app/libraries/myorg/person.php
namespace Lib\MyOrg;
use App\Models\Device;
use Lib\MyOrg\General;
class Person
{
protected $model;
protected $class;
public function __construct(General $generalclass, Device $device)
{
}
}
Run Code Online (Sandbox Code Playgroud)
dam*_*ani 12
你的助手类有一个循环依赖的情况,当与依赖注入混合时,使它们不可实例化......并且没有好的方法让它们工作并且易于测试.
有一些hack-y方法可以让它工作:
您可以使用setter注入,在使用帮助程序时在setter方法中注入依赖项,而不是在实例化时在构造函数中注入依赖项.这有许多缺点,其中可测试性差.(参见 http://symfony.com/doc/current/components/dependency_injection/types.html)
在Laravel 5中,您可以使用方法注入,特别是如果依赖关系仅与一个或两个方法相关.(见 http://mattstauffer.co/blog/laravel-5.0-method-injection)
您可以像上面提到的那样进行存在检查,或者使用事件监听器.但所有这一切都掩盖了......
循环依赖通常表示设计更改是有序的,最好通过重新考虑类如何相互交互来解决.
如果您的人员和普通班级完全相互依赖,那么他们可能共同承担一项责任,应该合并为一个班级.
但是,如果它们依赖于彼此功能的一个子集,那么可能有一个单独的类,其中有自己的责任隐藏在某处,然后最好的解决方案是将常用功能提取到第3类.这样,A类和B类依赖于A类,而不是A类依赖于B类,而A类和B类都依赖于C类.您可以安全地将它们全部实例化,并且它们都易于测试.
你怎么能容易地弄清楚你的新C类应该包含什么?一个很好的经验法则来自http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/ ..."列出你班级A中的所有方法由类B使用,以及类A使用的类B中的所有方法.两个列表中较短的一个是隐藏的类C."