为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
RISEBY 2023-08-19 16:35:03
我正在使用存储库模式从数据库中获取数据。这是我的基类: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()并“覆盖”它的返回类型,而不必重写整个函数?
查看完整描述

3 回答

?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

为什么要使用 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);

    }

}


查看完整回答
反对 回复 2023-08-19
?
婷婷同学_

TA贡献1844条经验 获得超8个赞

我不相信你可以“覆盖”/重写 PHP 上接口方法的返回类型。关于返回类型的 php 文档指出“继承期间的返回类型是不变的”:

继承期间声明的返回类型的强制执行是不变的;这意味着当子类型重写父方法时,子类型的返回类型必须与父类型完全匹配,并且不能省略。如果父级未声明返回类型,则允许子级声明返回类型。

一种可能的解决方案是创建第二个具有不同名称的方法,该方法ItemRepositoryInterface将调用并隐藏以下结果findOrFail

interface ItemRepositoryInterface extends EloquentRepositoryInterface{
    public function findOrFailItem($id): Item;
}


查看完整回答
反对 回复 2023-08-19
?
猛跑小猪

TA贡献1858条经验 获得超8个赞

EloquentRepository接口:

interface EloquentRepositoryInterface{
  public function findOrFail($id): ?Model;
}

语法 ?Model 将返回模型(如果存在)。对项目界面使用相同的方法


查看完整回答
反对 回复 2023-08-19
  • 3 回答
  • 0 关注
  • 124 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信