【问题标题】:PhpStorm metadata file for repository classes存储库类的 PhpStorm 元数据文件
【发布时间】:2018-05-11 07:50:10
【问题描述】:

在我们的应用程序中,我们使用从数据库中获取的模型的存储库。因此,我们有一个了解数据库的抽象存储库,有一个用于加载数据库记录的loadById 方法和一个为该特定存储库创建对象的抽象getEntity 方法。示例代码:

abstract class EntityRepository {
  /**
   * @param int $id
   * @return AbstractEntity
   */
  public function loadById($id) {
    $record = $this->db->loadById($id);
    $entity = $this->getEntity();
    return $this->inflate($record, $entity);
  }

  /**
   * @return AbstractEntity
   */
  protected abstract function getEntity();
}

class PeopleRepository extends EntityRepository {
  protected function getEntity() {
    return new PeopleEntity();
  }
}

abstract class AbstractEntity {
  private $id;

  /**
   * @return int
   */
  public function getId() {
    return $this->id;
  }

  /**
   * @param int $id;
   */
  public function setId($id) {
    $this->id = $id;
  }
}

class PeopleEntity extends AbstractEntity {
  private $name;

  /**
   * @return string
   */
  public function getName() {
    return $this->name;
  }

  /**
   * @param string $name;
   */
  public function setName($name) {
    $this->name= $name;
  }
}

当使用PeopleRepository 的实例并通过loadById 获取模型时,PhpStorm 无法将返回的模型解析为具体类型,而只为AbstractEntity 的功能提供代码补全。有什么简单的方法可以让它工作吗?

https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata 中,我只找到了使其适用于具体类及其功能的方法。因此,枚举所有存储库类及其创建实体的所有方式可能会起作用。但我希望看到一种抽象的定义方式,例如“加载实体时,EntityRepository 的所有实例都将返回getEntity() 中定义的那种类型的实体”

【问题讨论】:

  • 我不太确定我做对了这一切(太复杂了,如果没有完整的代码示例,我无法掌握它).. 但是为什么不在 @ 中描述 loadById() 的正确返回类型987654330@?通过@method PHPDoc 标签重新声明它。我相信这在这里会更正确..因为元数据方式是关于基于参数值的正确返回类型。
  • @LazyOne 没有必要在所有扩展存储库中覆盖loadById - 这就是抽象类的用途;)毕竟,我强烈简化了方法,不会使代码更长。抽象存储库中的方法可能很多且更长
  • 你没有覆盖它。实际方法(代码)未改动。这是关于提供正确的返回类型。 PHPDoc 中的简单一行 对类的注释 -- 就是这样。
  • 好的,我试过了,基本上它可以工作——直到你尝试跳转到loadById 的声明。它指向注解而不是实际的实现:(
  • 这是意料之中的。我怀疑你真的需要跳到那个实际的方法。但是如果你仍然需要它——之后调用Navigate | File Structure,它会列出当前类和父类的所有方法(或者其他可能更适合你的方法)。

标签: php phpstorm


【解决方案1】:

我怀疑是否有一种笼统的方法可以做到这一点。即使使用 PHPStorm 元数据,您也必须明确每种情况。也许这样做的方法是添加存储库外观,例如

class RepositoryFacade {
     public static function __callStatic($method, $args) {
          if ($args[0] == People::class) {
              array_shift($args);
              return new PeopleRepository()->{$method}(...$args); 
          }
     }
}

然后您可以使用以下方式输入提示:

override(RepositoryFacade::loadById(0), type(0));

当然,外观并不是一般使用的最佳模式,所以我可以看出这可能不是理想的。

【讨论】:

  • 但是如果我这样做,我必须覆盖外观中所有可能的实体类?添加新的实体存储库会导致编辑外观?那我宁愿手动将这样的新存储库类添加到元文件中
  • 我不想评判!如果我已经有了解决方案,我还没有发布我的问题;)如果这毕竟不可能以抽象的方式实现,我很乐意采取所有非好的解决方案中最好的;)
猜你喜欢
  • 2015-12-31
  • 2016-05-03
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多