存储库模式:如何准确函数的签名(返回类型)?

我正在使用存储库模式从数据库中获取数据。


这是我的基类:


class BaseRepository implements EloquentRepositoryInterface

{

 

  protected $model;


  public function __construct(Model $model)

  {

    $this->model = $model;

  }


  

  public function findOrFail($id): Model

  {

    try {

      return $this->model->findOrFail($id);

    } catch (\Exception $e) {

      throw new \Exception($e);

    }

  }


}

它实现了这个接口:


interface EloquentRepositoryInterface

{

  public function findOrFail($id): Model;

}

然后我有一个名为 的实体Item,它扩展了Model:


class Item extends Model

{

  // ... 

}

我想做的是创建一个 ItemRepositoryInterface:


interface ItemRepositoryInterface extends EloquentRepositoryInterface

{

  public function findOrFail($id): Item;

}

但我无法更改接口签名... PhpStorm 告诉我这是不兼容的,所以我必须public function findOrFail($id): Item从接口中删除它。所以我$itemRepository->findOrFail()尊重 的签名EloquentRepositoryInterface。


这是我的 ItemRepository :


class ItemRepository extends BaseRepository implements ItemRepositoryInterface

{

   // ...

}

问题

是当我使用$itemRepository->findOrFail()规格时告诉我它返回Model

我想要的是

是当我打电话时$itemRepository->findOrFail()规格应该告诉我它正在返回Item

有没有办法有这种行为?就像保留 EloquentRepositoryInterface 内部的签名findOrFail()并“覆盖”它的返回类型,而不必重写整个函数?


RISEBY
浏览 125回答 3
3回答

慕田峪9158850

为什么要使用 BaseRepository?您的问题的解决方案是泛型,但据我所知 php 不支持泛型。您有 3 个选择:您可以从返回类型的方法契约中删除类型信息,或者跳过该 BaseRepository。或者你根本不使用 eloquent 的存储库,因为 eloquent 使用 Active Record 模式,你的持久性将始终与你的模型绑定。因此,拥有一个额外的存储库层将所有内容委托给模型看起来有点开销,除非您想要抽象一些复杂的查询。如果您仍然想使用存储库,请选择第二个选项。interface ItemRepository {    public function findOrFail($id) : Item;}class EloquentItemRepository implements ItemRepository{    public function findOrFail($id) : Item {        return Item::findOrFail($id);    }}

婷婷同学_

我不相信你可以“覆盖”/重写 PHP 上接口方法的返回类型。关于返回类型的 php 文档指出“继承期间的返回类型是不变的”:继承期间声明的返回类型的强制执行是不变的;这意味着当子类型重写父方法时,子类型的返回类型必须与父类型完全匹配,并且不能省略。如果父级未声明返回类型,则允许子级声明返回类型。一种可能的解决方案是创建第二个具有不同名称的方法,该方法ItemRepositoryInterface将调用并隐藏以下结果findOrFail:interface ItemRepositoryInterface extends EloquentRepositoryInterface{     public function findOrFailItem($id): Item; }

猛跑小猪

EloquentRepository接口:interface EloquentRepositoryInterface{   public function findOrFail($id): ?Model; }语法 ?Model 将返回模型(如果存在)。对项目界面使用相同的方法
打开App,查看更多内容
随时随地看视频慕课网APP