Zend framework2 zend framework 2了解exchangeArray方法

Zend framework2 zend framework 2了解exchangeArray方法,zend-framework2,tablegateway,Zend Framework2,Tablegateway,从: 我们的Album实体对象是一个简单的PHP类。为了使用Zend\Db的TableGateway类,我们需要实现exchangeArray()方法。此方法只是将传入数组中的数据复制到实体的属性中 好的,我们需要。但是这个函数的用途是什么 我的意思是,我已经理解了这个函数的功能,但是我不理解它为什么会这样做 真的有必要声明所有变量吗 假设我有一个包含20列的表,我想将它们全部选中。 然后我应该声明20个命名变量 如果我想区分公共(打印)变量和私有(内部)变量,这是有意义的 还有其他原因吗?这不

从:

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

好的,我们需要。但是这个函数的用途是什么

我的意思是,我已经理解了这个函数的功能,但是我不理解它为什么会这样做

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

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

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


还有其他原因吗?

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

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框架提供了更复杂的水合作用方式。如果数据库表中的releaseDate列的类型为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
对象

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

最后但并非最不重要的一点:IDE支持。如果您的实体对象是严格的php文档注释对象,那么您的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;
    }
}

本例假设表网关是通过相应的工厂创建的。

您的答案很好,但我有点困惑:您的话大体正确吗?我的意思是,据我所知,为了应用您的示例,我需要在给定的示例使用默认的ArraySerializable时,使用ClassMethods或来初始化TableGateway。我说的对吗?你在开场白中给出的例子是使用ArraySerializable接口。你完全正确。您必须使用类方法实例化表网关。我将编辑我的答案,并给出一个如何实例化表网关的示例。
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;
    }
}