0

文档中:

 namespace Album\Model;

 class Album
 {
     public $id;
     public $artist;
     public $title;

     public function exchangeArray($data)
     {
         $this->id     = (!empty($data['id'])) ? $data['id'] : null;
         $this->artist = (!empty($data['artist'])) ? $data['artist'] : null;
         $this->title  = (!empty($data['title'])) ? $data['title'] : null;
     }
 }

我们的 Album 实体对象是一个简单的 PHP 类。为了使用 Zend\Db 的 TableGateway 类,我们需要实现 exchangeArray() 方法。此方法只是将传入数组中的数据复制到我们实体的属性中

好的,我们需要。但是该功能的用途是什么?

我的意思是,我已经理解那个函数的作用,但我不明白为什么它会那样做

真的有必要声明所有变量吗?

假设我有一个包含 20 列的表格,我想将它们全部选中。然后我应该声明 20 个命名变量。

如果我想区分公共(打印)和私有(内部)变量,这是有道理的。

还有其他原因吗?

4

1 回答 1

1

这不仅仅是定义类成员。它更多的是关于面向对象的好处,如封装、继承等。假设您的实体如下所示:

declare(strict_types=1);
namespace Application\Entity;

class Album
{
    protected $id;

    protected $artist;

    protected $title;

    public function getId() : int
    {
        return $this->id;
    }

    public function setId(int $id) : Album
    {
         $this->id = $id;
         return $this;
    }

    public function getArtist() : string
    {
        return $this->artist;
    }

    public function setArtist(string $artist) : Album
    {
        $this->artist = $artist;
        return $this;
    }

    public function getTitle() : string
    {
        return $this->title;
    }

    public function setTitle(string $title) : Album
    {
        $this->title = $title;
        return $this;
    }
} 

使用实体的第一个优势:不可能出现拼写错误。$data['atrist'] = 'Marcel'在大多数情况下都可以使用。$album->setAtrist('Marcel')会抛出错误。

第二个优点是类型提示。特别是当您使用 PHP7 时,您可以利用类型提示的优势。$album->setId('1')将抛出错误,因为此方法需要一个整数值。

第三个优点是可以向您的实体添加一些额外的代码。如果我们需要发布日期但没有给出发布日期怎么办?您可以在实体中验证事物。

protected $releaseDate;

public function getReleaseDate() : \DateTime
{
    if ($this->releaseData == null) {
        throw new \Exception('no release date given. evacuate!');
    }

    return $this->releaseDate;
}

另一个优点是 zend 框架中的水合作用。虽然该exchangeArray方法是一种简单的水合,但zend框架提供了更复杂的水合方式。如果您在数据库表中的发布日期列是 DATE 类型,并且您希望实体中的 releaseDate 成员成为\DateTime表示此日期的对象,那该怎么办?

// data from your database
$data = [
    'id' => 1,
    'artist' => 'the outside agency',
    'title' => 'scenocide 202',
    'releaseDate' => '2010-06-30',
];

// hydration of your entity with zend 's own hydrator classes
$album = (new ClassMethods())
    ->addStrategy('releaseDate', new DateTimeStrategy('Y-m-d'))
    ->hydrate($data, new Album());

$releaseDate = $album->getReleaseDate()->format('d.m.Y');

如您所见,发布日期是一个简单的字符串。在为实体补水时,发布日期将通过补水\DateTime策略转换为对象。

这些好处不仅仅是区分公共变量、受保护变量和私有变量。实体只接受和提供变量,这些变量应该在您的实体中。你可以使用所有 oo 的东西,比如继承(实现\JsonSerializable接口有时很神奇)、类型提示、封装、多态等等......

最后但同样重要的是:IDE 支持。如果您的实体对象是严格的 php doc 注释,那么您的 IDE 知道您可以对您的实体做什么。为您减少工作量。;)

编辑:表网关实例化与水合结果集

要在表网关中使用实体对象的上述优势和水合器,您必须像下面的示例一样实例化表网关。

class AlbumTableGateway extends TableGateway
{
    public function __construct(Adapter $adapter)
    {
        $resultset = new HydratingResultset(
            (new ClassMethods())->addStrategy('releaseDate', new DateTimeFormatter()),
            new AlbumEntity()
        );

        parent::__construct('album_table', $adapter, null, $resultset);
    }

    public function fetchById($id)
    {
        $select = $this->getSql()->select();
        $select->columns([
            'id',
            'artist',
            'title',
            'releaseDate',
        ]);

        $select->where->equalTo('id', $id);

        $result = $this->selectWith($select);

        // get the found resultset with $result->current()->getId();
        return $result;
    }
}

此示例假设 Table Gateway 是通过相应的工厂创建的。

于 2018-02-22T22:57:53.490 回答