Laravel 4使用IoC容器建立模型


Laravel 4 setting up model using the IoC container

我最近看了这个视频,想更改我的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,它对我很有效。