zend framework 2 理解exchangeArray方法

zend framework 2 understanding the exchangeArray method

来自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;
     }
 }

Our Album entity object is a simple PHP class. In order to work with Zend\Db’s TableGateway class, we need to implement the exchangeArray() method. This method simply copies the data from the passed in array to our entity’s properties

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

我的意思是,我已经理解 该函数的作用,但我无法理解 为什么它会那样做

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

假设我有一个 table 的 20 列,我想 select 全部。 那么我应该声明 20 个命名变量。

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

还有其他原因吗?

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

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 框架提供了更复杂的水化方式。如果您在数据库 table 中的发布日期列是 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 对象。

这些好处远不止区分 public、受保护变量和私有变量。一个实体只接受并提供变量,这些变量应该在您的实体中。您可以使用所有面向对象的事物,例如继承(实现 \JsonSerializable 接口有时非常神奇)、类型提示、封装、多态性等等...

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

编辑:Table 带有保湿结果集的网关实例化

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

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 网关是通过相应的工厂创建的。