【问题标题】:Can't use superclass in Repository implementation in PHP无法在 PHP 的存储库实现中使用超类
【发布时间】:2017-03-30 09:36:50
【问题描述】:

我正在尝试在 PHP 中实现非常基本的存储库模式。

假设我需要一个通用接口来处理通用实体存储:

<?php

interface IRepository
{
    public function persist(Entity $entity);
    // reduced code for brevity
}

现在我构建实体类型层次结构:

<?php

abstract class Entity
{
    protected $id;

    protected function getId()
    {
        return $this->id;
    }
}

这是 Post 类:

<?php

class Post extends Entity
{
    private $title;

    private $body;
}

现在我想使用 PDO 支持的数据库来存储帖子:

<?php

use PDO;

abstract class DatabaseRepository implements IRepository
{
    protected $pdo;

    protected $statement;

    public function __construct(PDO $pdo)
    {
        $this->pdo = $pdo;
    }
}

现在我尝试实现 IRepository 接口

<?php

class PostRepository extends DatabaseRepository
{

    // I have an error here 
    //  Fatal error: Declaration of PostRepository::persist(Post $post) must be compatible with IRepository::persist(Entity $entity) 
    public function persist(Post $post)
    {
    }
}

如您所见,这会引发致命错误。在 PostRepository::persist() 中使用类型提示我保证我使用 Entity 子对象来满足 IRepository 要求。那么为什么会抛出这个错误呢?

【问题讨论】:

  • 错误似乎很明显。 persist(Post $post) 必须是 persist(Entity $entity)
  • 您正在寻找泛型,它的工作方式类似于 JAVA 中的 this。我不确定是否有 PHP 的解决方案,我知道 HHVM 有。我去看看

标签: php repository-pattern irepository


【解决方案1】:

正如我所说,您正在寻找泛型。目前不可能像JAVAC# 一样,但是在HHVM

对于 PHP,rfc 仍处于草稿状态。 https://wiki.php.net/rfc/generics

因此,如果您真的想这样做,您可以创建一个更通用的接口并进行一些类型检查,或者将Post 设为Entity 的子类,或者同时设为另一个父级的子类(但这会产生严格的警告)。

【讨论】:

  • 感谢@Timmetje 提供完整的答案。但是如上所示“使 Post 成为 Entity 的子类”以从 Entity 扩展 Post 还不够好吗?
  • 您可以这样做,因为 Post 将是 Entity 的一个实例,但 PHP 会抛出严格的警告。你应该玩弄它,看看它是否符合你的需要。
  • 再次感谢@Timmetje!
猜你喜欢
  • 1970-01-01
  • 2022-11-16
  • 2016-04-20
  • 2013-11-21
  • 2021-05-14
  • 1970-01-01
  • 2014-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多