将带有表单集合的表单绑定到 ZF2 中的实体


Binding a Form with Form Collections to an Entity in ZF2

我设置了一个基本的概念证明,涉及音乐家和专辑,用于在Zend Framework中将表单与表单集合绑定。

这是音乐家类:

<?php
namespace Application'Entity;

class Musician {
protected $name;
protected $albums;
public function setName($name)
{
    $this->name = $name;
    return $this;
}
public function getName()
{
    return $this->name;
} 
public function setAlbums($album)
{
   $this->album = $album;
   return $this;
}
public function getAlbums()
{
    return $this->albums;
}

这是专辑类:

<?php
namespace Application'Entity;

class Album {
protected $name;
protected $releaseYear;
public function setName($name)
{
    $this->name = $name;
    return $this;
}
public function getName()
{
    return $this->name;
}
public function setReleaseYear($releaseYear)
{
   $this->releaseYear = $releaseYear;
   return $this;
}
public function getReleaseYear()
{
    return $this->releaseYear;
}

}

专辑字段集:

专辑字段集:

<?php
namespace Application'Form'Music;
use Zend'Form'Fieldset;
use Zend'Stdlib'Hydrator'ClassMethods;
use Zend'Validator; 
use Zend'Form'Element;
use Application'Entity'Album;
use Zend'ServiceManager'ServiceLocatorAwareInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
use Zend'InputFilter'InputFilterProviderInterface;
class AlbumFieldSet extends Fieldset implements  InputFilterProviderInterface,         ServiceLocatorAwareInterface
{

   public function __construct()
   {
   parent::__construct('album');
   $this->setObject(new Album());
   $this->setHydrator(new ClassMethods());

   $this->add(array(
       'type' => 'Text',
       'name' => 'name',
       'options' => [
       ]
   ));
   $this->add(array(
       'type' => 'Text',
       'name' => 'releaseYear',
       'options' => [
       ]
   ));

  }
   public function init()
   {
   } 


   /**
    * Should return an array specification compatible with
    * {@link Zend'InputFilter'Factory::createInputFilter()}.
    *
    * @return array
    */
   public function getInputFilterSpecification()
   {
   return [
       'name' => array(
           'required' => true,
           'validators' => array(
           )
       ),
   ];
 }
  /**
   * Set service locator
   *
   * @param ServiceLocatorInterface $serviceLocator
   */
  public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
  {
      $this->sl = $serviceLocator;
  }
  /**
   * Get service locator
   *
   * @return ServiceLocatorInterface
   */
  public function getServiceLocator()
  {
      return $this->sl;
  }
}

这是音乐家表格

<?php
namespace Application'Form'Music;
use Application'Entity'Album;
use Zend'Form'Form;
use Zend'Form'Element'Collection;
use Zend'Stdlib'Hydrator'ClassMethods;
use Zend'Stdlib'Hydrator'ObjectProperty;
use Zend'Validator;
use Zend'Form'Element;
use Application'Form'Music'AlbumFieldset;
use Zend'ServiceManager'ServiceLocatorAwareInterface;
use Zend'ServiceManager'ServiceLocatorInterface;
use Zend'InputFilter'InputFilterProviderInterface;
class MusicianForm extends Form implements  InputFilterProviderInterface, ServiceLocatorAwareInterface
{

   public function __construct()
   {
       parent::__construct('');
   }
   public function init()
   {
   }

   public function setMusician($musician) {
       $this->setHydrator(new ClassMethods());
       $this->add(array(
           'type' => 'Text',
           'name' => 'name',
           'options' => [
           ]
       ));


       $this->buildFields();
       $this->bind($musician);
   }

   public function buildFields() {

       $fs = new AlbumFieldSet();
       $fs->setHydrator(new ObjectProperty());
       $fs->setObject(new Album());
       $this->add(array(
           'type' => 'Zend'Form'Element'Collection',
           'name' => 'albums',
           'options' => array(
               'label' => 'Form Values',
               'count' => 2,
               'allow_add' => false,
               'allow_remove' => false,
               'should_create_template' => false,
               'target_element' => $fs,
               'use_as_base_fieldset' => true,
           ),
       ));
   }

   /**
    * Should return an array specification compatible with
    * {@link Zend'InputFilter'Factory::createInputFilter()}.
    *
    * @return array
    */
   public function getInputFilterSpecification()
   {
       return [
           'name' => array(
               'required' => true,
               'validators' => array(
               )
           ),
       ];
   }
   /**
    * Set service locator
    *
    * @param ServiceLocatorInterface $serviceLocator
    */
   public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
   {
       $this->sl = $serviceLocator;
   }
   /**
    * Get service locator
    *
    * @return ServiceLocatorInterface
    */
   public function getServiceLocator()
   {
       return $this->sl;
   }
}

控制器代码:

<?php
namespace Application'Controller;
use Zend'Mvc'Controller'AbstractActionController;
use Zend'View'Model'ViewModel;
use Application'Entity'Musician as Musician;
use Application'Entity'Album as Album;

class MusiciansController extends AbstractActionController
{
   public function createMusicianAction()
   {

       $musician = new Musician();
       $albumOne = new Album();
       $albumTwo = new Album();
       $albumOne->setName('The White Album');
       $albumTwo->setName('Sgt. Pepper');
       $albumOne->setReleaseYear('1974');
       $albumTwo->setReleaseYear('1967');
       $albums = array(
           $albumOne,
           $albumTwo
       );
       $musician->setName('The Beatles');
       $musician->setAlbums($albums);
       $form = $this->getServiceLocator()->get('FormElementManager')->get('MusicianForm');
       $form->setMusician($musician);
       return new ViewModel([
]);
   }
}

当我尝试绑定表单时,我最终出现以下错误:

Zend'Form'Element'Collection::setObject expects an array or Traversable object argument; received "Application'Entity'Musician"

我试图在音乐家类中实现迭代器,但那里的解决方案似乎很复杂,而且不太清楚。如何让此绑定正常工作?

我想通了!

这里的问题是Zend框架要求所有与表单相关的实体都有自己的字段集,以便绑定正常工作

在此特定示例中,我创建了一个音乐家字段集,将其设置为音乐家窗体

中的基本字段集,并在音乐家字段集中创建了专辑窗体集合。瞧!一切都填充得很好。