繁体   English   中英

如何在Zend Framework 2的嵌套映射器模型类中使用InputFilter?

[英]How to use the InputFilter in a nested mapper model class in Zend Framework 2?

通过“入门”教程开始ZF2学习的每个人都将知道模型类Album (下)。

现在,我想用歌曲扩展我的模型。 一张专辑可以包含0首或更多歌曲。 这些歌曲将获得新的talbe songsidtitlealbum_id )和映射器Album\\Model\\Song 映射器Album\\Model\\Song构建类似于Album\\Model\\Album 映射器Album\\Model\\Album将获得一个新的属性songCollectionAlbum\\Model\\Song对象的数组,或者像是Album\\Model\\SongCollection对象的数组)。

  • InputFilter用于“嵌套”(映射器)类是否InputFilter
  • 应该如何修改getInputFilter()
  • 应该如何修改setInputFilter() 好的,现在根本没有实现。 但是,对于一个浅层的类结构来说,几乎是很清楚的-并不清楚如何为引用另一个mapper的mapper实现它。

Album\\Model\\Album

<?php
namespace Album\Model;

use Zend\Stdlib\ArraySerializableInterface;

use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;

class Album implements InputFilterAwareInterface, ArraySerializableInterface {

    public $id;
    public $artist;
    public $title;

    protected $inputFilter;

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

    public function toArray() {
        return $this->getArrayCopy();
    }

    public function getArrayCopy() {
        return get_object_vars($this);
    }

    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception('Not used');
    }

    public function getInputFilter() {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();
            $factory = new InputFactory();

            $inputFilter->add($factory->createInput(array(
                'name' => 'id',
                'required' => true,
                'filters' => array(
                    array('name' => 'Int')
                )
            )));

            $inputFilter->add($factory->createInput(array(
                'name' => 'artist',
                'required' => true,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim')
                ),
                'validarots' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 1,
                            'max' => 100
                        )
                    )
                )
            )));

            $inputFilter->add($factory->createInput(array(
                'name' => 'title',
                'required' => true,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim')
                ),
                'validarots' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 1,
                            'max' => 100
                        )
                    )
                )
            )));

            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }

}

我认为您对该示例中列出的模型和映射器的关系有些困惑。

“映射器”将是TableGateway对象,例如AlbumTable,SongTable等。专辑和Song类将称为模型或域对象,它们代表应用程序中的实际实体。 映射器只需要将它们持久保存在数据库中等等。

使用TableGateway实现时,我将让每个域对象(例如Ablum)处理其TableGateway将要保留的属性(例如AlbumTable)的InputFilter。

对于您所说的示例,我根本不会更改专辑模型的InputFilter。 原因是与歌曲的关系是这样的:

Album HAS many songs, Song Belongs to Album (the Song would have the link back to the Album)

添加一个新的歌曲对象和网关:

<?php
namespace Album\Model;

use Zend\Stdlib\ArraySerializableInterface;

use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;

class Song implements InputFilterAwareInterface, ArraySerializableInterface {

    protected $id;
    protected $album;
    protected $title;

    protected $inputFilter;

    // Added Getters / Setters for the attributes rather than
    // having public scope ...

    public function setAlbum(Album $album)
    {
         $this->album = $album;
    }

    public function getAlbum()
    {
        return $this->album;
    }

    public function exchangeArray(array $data) {
        $this->id     = (isset($data['id'])) ? $data['id'] : null;
        $this->title  = (isset($data['title'])) ? $data['title'] : null;

        if(isset($data['album_id'])) {
             $album = new Album();
             $album->exchangeArray($data['album_id']);
             $this->setAlbum($album);
        }
    }

    public function toArray() {
        return $this->getArrayCopy();
    }

    public function getArrayCopy() {
        return array(
             'id'       => $this->id,
             'album_id' => $this->getAlbum()->id,
             'title'    => $this->title,
        );
    }

    public function setInputFilter(InputFilterInterface $inputFilter) {
        throw new \Exception('Not used');
    }

    public function getInputFilter() {
        if (!$this->inputFilter) {
            $inputFilter = new InputFilter();
            $factory = new InputFactory();

            $inputFilter->add($factory->createInput(array(
                'name' => 'id',
                'required' => true,
                'filters' => array(
                    array('name' => 'Int')
                )
            )));

            $inputFilter->add($factory->createInput(array(
                'name' => 'album_id',
                'required' => true,
                'filters' => array(
                    array('name' => 'Int')
                )
            )));

            $inputFilter->add($factory->createInput(array(
                'name' => 'title',
                'required' => true,
                'filters' => array(
                    array('name' => 'StripTags'),
                    array('name' => 'StringTrim')
                ),
                'validarots' => array(
                    array(
                        'name' => 'StringLength',
                        'options' => array(
                            'encoding' => 'UTF-8',
                            'min' => 1,
                            'max' => 100
                        )
                    )
                )
            )));

            $this->inputFilter = $inputFilter;
        }
        return $this->inputFilter;
    }
}

请注意,由于关系为“歌曲属于专辑”,因此无需更改专辑模型。

当对象关系变得更加复杂时,您将需要考虑使用Hydrators为您构建对象( http://framework.zend.com/manual/2.0/en/modules/zend.stdlib.hydrator.html

现在,您将创建一个SongTable来为您持久存储此新对象:

<?php
namespace Album\Model;

use Zend\Db\TableGateway\TableGateway;

class SongTable
{
    protected $tableGateway;

    public function __construct(TableGateway $tableGateway)
    {
        $this->tableGateway = $tableGateway;
    }

    public function fetchAll()
    {
        $resultSet = $this->tableGateway->select();
        return $resultSet;
    }

    public function getSong($id)
    {
        $id  = (int) $id;
        $rowset = $this->tableGateway->select(array('id' => $id));
        $row = $rowset->current();
        if (!$row) {
            throw new \Exception("Could not find row $id");
        }
        return $row;
    }

    public function saveSong(Song $song)
    {
        $data = array(
            'album_id' => $song->getAlbum()->id,
            'title'    => $song->title,
        );

        $id = (int)$song->id;
        if ($id == 0) {
            $this->tableGateway->insert($data);
        } else {
            if ($this->getSong($id)) {
                $this->tableGateway->update($data, array('id' => $id));
            } else {
                throw new \Exception('Form id does not exist');
            }
        }
    }

    public function fetchAlbumSongs(Album $album)
    {
        $resultSet = $this->tableGateway->select(array(
            'album_id' => $album->id
        ));

        return $resultSet;
    }

    public function addSongsToAlbum(Album $album)
    {
        foreach($this->fetchAlbumSongs($album) as $song) {
            $album->addSong($song);
        }
    }
}

然后,您可以修改专辑模型以允许添加歌曲:

class Album implements InputFilterAwareInterface, ArraySerializableInterface {

    // Other stuff here

    /**
     * @var array
     */
    protected $songs = array();

    public function addSong(Song $song)
    {
        $this->songs[] = $song;
    }

    public function getSongs()
    {
         return $this->songs;
    }
}

然后,您可以轻松地构建对象图,通常我会让服务器来做这种事情:

AlbumService.php

public function getAlumbWithSongs(int $id)
{
    $album = $this->getAlbumTable()->getAlbum($id);

    if($album) {
        $this->getSongTable()->addSongsToAlbum($album);
    }

    return $album;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM