[英]How to use the InputFilter in a nested mapper model class in Zend Framework 2?
通過“入門”教程開始ZF2學習的每個人都將知道模型類Album
(下)。
現在,我想用歌曲擴展我的模型。 一張專輯可以包含0首或更多歌曲。 這些歌曲將獲得新的talbe songs
( id
, title
, album_id
)和映射器Album\\Model\\Song
。 映射器Album\\Model\\Song
構建類似於Album\\Model\\Album
。 映射器Album\\Model\\Album
將獲得一個新的屬性songCollection
( Album\\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.