代码之家  ›  专栏  ›  技术社区  ›  Gwen Hufschmid

zend framework 2了解exchangeArray方法

  •  0
  • Gwen Hufschmid  · 技术社区  · 8 年前

    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 回复  |  直到 8 年前
        1
  •  1
  •   Marcel    8 年前

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

    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');
    

    正如您所看到的,发布日期是一个简单的字符串。在为身体补水的同时,发布日期将变为 \日期时间 通过水合器策略。

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

    最后但并非最不重要的一点: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;
        }
    }
    

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