我目前正在开发我的第一个PHP / Laravel 4项目,我正在开发一个存储类,为第三方库添加Eloquent支持。
我的EloquentStorage类从库中扩展了AbstractStorage类,并且我使用了大多数AbstractStorage方法。现在我想为我的新EloquentStorage类添加Eloquent支持,我遇到了PHP不支持多重继承的事实。
是否有正确的方法来定义Eloquent模型而不将其扩展为:
class MyClass extends Eloquent {}
而且,如果没有,当我需要扩展第三方课程并扩展Eloquent时如何处理这种情况?也许使用Laravel的IoC?
答案 0 :(得分:1)
我认为您的模型应该从Eloquent
延伸,而是通过repository访问。您的存储库可以具有$storage
属性,并且负责在AbstractStorage
实现上调用相应的方法。下面是伪实际代码而不是实际代码,但说明了可以插入实现以进行更新操作的地方。
class MyClass extends Eloquent
{
/* Normal Eloquent model implementation */
}
class MyRepository
{
protected $storage;
protected $myClass;
public function __construct(MyClass $myClass, AbstractStorage $storage)
{
$this->myClass = $myClass;
$this->storage = $storage;
}
public function update($id, $data)
{
// This is just an example operation, basically here's your chance to call
// the 3rd-party implementation. Here is pre-eloquent update, but can be
// after
$this->storage->update($id, $data);
// Use the empty Eloquent class property instance to obtain an instance of
// the requested model
$instance = $this->myClass->find($id);
// set instance properties
$instance->save();
// Example post-eloquent update
$this->storage->update($id, $data);
}
}
class MyStorage extends AbstractStorage { /* Your Storage Implementation */ }
$repo = new MyRepository(new MyClass, new MyStorage);
// Update item id 42's foo property
$repo->update(42, [ 'foo' => 'bar' ]);
这种方法的一个好处是存储库本身的构造可以通过服务提供程序卸载到IoC,并注入控制器/表单验证器等内部,这意味着执行将变为自动并隐藏底层来自系统其他部分的第三方库的复杂性(存储库有助于保持第3方抽象不受leaking的影响)。
另一个好处是,您的雄辩模型中不需要任何与您完全无关的第三方代码有关的特殊代码。所有逻辑都封装在一个位置,甚至可以在多个模型之间共享。想要改变第三方提供商?编写AbstractStorage
的新实现,更新服务提供商,然后就完成了。
另一个好处是提高了可测试性。而不是直接静态地利用雄辩的模型(la $user = User::find($id)
),而是操纵你的存储库对象($user = $this->repo->find($id)
)。由于您的存储库可以轻易地进行模拟并自行测试(无需测试Eloquent或访问数据库),因此您可以在所有控制器路由上编写集成测试,并了解代码库更改会破坏业务规则的时刻。