zend框架2了解exchangeArray方法

时间:2018-02-22 15:09:43

标签: zend-framework2 tablegateway

来自documentation

 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个命名变量。

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

还有其他原因吗?

1 个答案:

答案 0 :(得分: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对象。

这些好处不仅仅是区分公共变量,受保护变量和私有变量。实体只接受并提供应该在您的实体中的变量。你可以使用所有的东西,比如继承(有时候实现\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;
    }
}

此示例假定表网关是通过相应的工厂创建的。