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

时间:2013-06-28 21:15:51

标签: orm model zend-framework2 zend-inputfilter

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

现在我想用歌曲扩展我的模型。一张专辑可以有0首或更多首歌曲。这些歌曲将获得新的标记songsidtitlealbum_id)和映射器Album\Model\Song。映射器Album\Model\Song的构建方式与Album\Model\Album类似。映射器Album\Model\Album将获得一个新属性songCollectionAlbum\Model\Song个对象的数组,或类似Album\Model\SongCollection对象的内容。

  • 是否可以将InputFilter用于“嵌套”(映射器)类?
  • 如何修改getInputFilter()
  • 如何修改setInputFilter()?好的,现在根本没有实现。但是很清楚如何为浅层结构做这件事 - 并且不清楚如何为映射器实现它,引用另一个映射器(-s)。

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

}

1 个答案:

答案 0 :(得分:1)

我认为你对这个例子中列出的模型和映射器的关系有点困惑。

'mappers'将是TableGateway对象,例如AlbumTable,SongTable等。专辑和歌曲类可以调用模型或域对象,它们代表应用程序中的实际实体。 Mappers只需要将它们保存在您的数据库等中。

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

对于您所说的示例,我根本不会更改Album Models 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;
    }
}

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

当您的对象关系变得更复杂时,您会想要使用Hydrator为您构建对象(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;
}