我最近看了这个视频,想更改我的Laravel控制器,以便用Laravel的IoC容器管理它们的依赖关系。视频讲述了为模型创建一个接口,然后为所使用的特定数据源实现该接口。
我的问题是:当用扩展Eloquent的类实现接口并将该类绑定到控制器以使其可以从$this->model
访问时,我是否也应该为调用方法(如$this->model->find($id)
)时可能返回的Eloquet模型创建接口和实现?模型和模型库是否应该有不同的类?
换句话说:当我的模型在$this->model
中时,我如何执行new Model
。
一般来说,是的,执行该模式(存储库模式)的人都有一个界面,其中定义了一些应用程序将使用的方法:
interface SomethingInterface {
public function find($id);
public function all();
public function paged($offset, $limit);
}
然后创建一个实现。如果你正在使用Eloquent,那么你可以制作一个Eloquet实现
use Illuminate'Database'Model;
class EloquentSomething {
protected $something;
public function __construct(Model $something)
{
$this->something = $something;
}
public function find($id)
{
return $this->something->find($id);
}
public function all() { ... }
public function paged($offset, $limit) { ... }
}
然后,您创建一个服务提供商,将其整合在一起,并将其添加到app/config/app.php
中。
use Something; // Eloquent Model
use Namespace'Path'To'EloquentSomething;
use Illuminate'Support'ServiceProvider;
class RepoServiceProvider extends ServiceProvider {
public function register()
{
$app = $this->app;
$app->bind('Namespace/Path/To/SomethingInterface', function()
{
return new EloquentSomething( new Something );
});
}
}
最后,您的控制器可以使用该接口作为类型提示:
use Namespace/Path/To/SomethingInterface;
class SomethingController extends BaseController {
protected $something;
public function __construct(SomethingInterface $something)
{
$this->something = $something;
}
public function home() { return $this->something->paged(0, 10); }
}
应该是这样。对任何错误道歉,这没有经过测试,但我经常做。
缺点:
更多代码:D
优点:
- 能够切换实现(而不是EloquentSomething,可以使用ArraySomething、MongoSomething等),而无需更改控制器代码或任何使用接口实现的代码
- 可测试-您可以模拟Eloquent类并测试存储库,或者模拟构造函数依赖关系并测试控制器
- 可重用-您可以
App::make()
在应用程序中的任何位置获取具体的EloquentSomething,并在代码中的任何地方重用Somethings存储库 - 存储库是添加额外逻辑的好地方,比如缓存层,甚至验证规则。股票在你的控制器里乱搞
最后:,因为我可能已经输入了所有内容,但仍然没有回答您的问题(wtf?!),所以您可以使用$this->model
获得模型的新实例。这里有一个创建新东西的例子:
// Interface:
public function create(array $data);
// EloquentSomething:
public function create(array $data)
{
$something = this->something->newInstance();
// Continue on with creation logic
}
关键是这个方法,newInstance()。
我使用过$newModel = $this->model
,它对我很有效。