2015-04-07 254 views
0

我有以下设置:ZF2:表格嵌套字段集 - 学说保湿尝试添加新实体的所有对象

我有一些相关的学说实体Product主义对象。

/** 
* Product 
* 
* @ORM\Table(name="products") 
* @ORM\Entity(repositoryClass="\Entities\ProductRepository") 
*/ 

class Product 
{ 
/** 
* @var integer 
* 
* @ORM\Column(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false) 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="IDENTITY") 
*/ 
private $id; 

/** 
* @var string 
* 
* @ORM\Column(name="artist", type="string", length=100, precision=0, scale=0, nullable=false, unique=false) 
*/ 
private $artist; 

/** 
* @var string 
* 
* @ORM\Column(name="title", type="string", length=100, precision=0, scale=0, nullable=false, unique=false) 
*/ 
private $title; 

/** 
* @var string 
* 
* @ORM\Column(name="subtitle", type="string", length=100, precision=0, scale=0, nullable=true, unique=false) 
*/ 
private $subtitle; 

/** 
* @var string 
* 
* @ORM\Column(name="labelcode", type="string", length=100, precision=0, scale=0, nullable=false, unique=false) 
*/ 
private $labelcode; 

/** 
* @var string 
* 
* @ORM\Column(name="description", type="string", length=100, precision=0, scale=0, nullable=true, unique=false) 
*/ 
private $description; 

/** 
* @var string 
* 
* @ORM\Column(name="hints", type="text", precision=0, scale=0, nullable=true, unique=false) 
*/ 
private $hints; 

/** 
* @var string 
* 
* @ORM\Column(name="price", type="decimal", precision=0, scale=2, nullable=false, unique=false) 
*/ 
private $price; 

/** 
* @var integer 
* 
* @ORM\Column(name="amount", type="integer", precision=0, scale=0, nullable=true, options={"default" = 0}, unique=false) 
*/ 
private $amount; 

/** 
* @var string 
* 
* @ORM\Column(name="image", type="string", length=100, precision=0, scale=0, nullable=true, unique=false) 
*/ 
private $image; 

/** 
* @var \DateTime 
* 
* @ORM\Column(name="instockdate", type="date", precision=0, scale=0, nullable=true, unique=false) 
*/ 
private $instockdate; 

/** 
* @var boolean 
* 
* @ORM\Column(name="ownrelease", type="boolean", precision=0, scale=0, nullable=true, columnDefinition="BOOLEAN DEFAULT FALSE", unique=false) 
*/ 
private $ownrelease; 

/** 
* @var \Entities\Label 
* 
* @ORM\ManyToOne(targetEntity="Entities\Label", inversedBy="products") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="label_id", referencedColumnName="id", nullable=false) 
* }) 
*/ 
private $label; 

/** 
* @var \Entities\Genre 
* 
* @ORM\ManyToOne(targetEntity="Entities\Genre", inversedBy="products")) 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="genre_id", referencedColumnName="id", nullable=false) 
* }) 
*/ 
private $genre; 

/** 
* @var \Entities\Type 
* 
* @ORM\ManyToOne(targetEntity="Entities\Type") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="type_id", referencedColumnName="id", nullable=false) 
* }) 
*/ 
private $type; 

/** 
* @var \Entities\Webshop 
* 
* @ORM\ManyToOne(targetEntity="Entities\Webshop", inversedBy="products") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="webshop_id", referencedColumnName="id", nullable=true) 
* }) 
*/ 
private $webshop; 

/** 
* @var \Entities\Supplier 
* 
* @ORM\ManyToOne(targetEntity="Entities\Supplier") 
* @ORM\JoinColumns({ 
* @ORM\JoinColumn(name="supplier_id", referencedColumnName="id", nullable=true) 
* }) 
*/ 
private $supplier; 

/** Getters and Setters **/ 
} 

我有一个CreateProductForm

class CreateProductForm extends Form implements InputFilterProviderInterface 
{ 

protected $objectManager; 

public function __construct(ObjectManager $objectManager) 
{ 
    parent::__construct('create-product-form'); 
    $this->setObjectManager($objectManager); 

    $this->setHydrator(new DoctrineHydrator($this->getObjectManager())); 

    $this->addElements(); 
} 

public function addElements() 
{ 
    // Add the product fieldset, and set it as the base fieldset 
    $productFieldset = new ProductFieldSet($this->getObjectManager()); 
    $productFieldset->setUseAsBaseFieldset(true); 
    $this->add($productFieldset); 

    // Add a checkbox allowing creation of another \Entities\Product 
    $this->add(array(
     'type' => 'Zend\Form\Element\Checkbox', 
     'name' => 'create_another_product', 
     'attributes' => array(
      'required' => FALSE, 
      'allow_empty' => TRUE, 
     ), 
     'options' => array(
      'label' => 'Create another', 
      'use_hidden_element' => TRUE, 
      'checked_value' => TRUE, 
      'unchecked_value' => FALSE, 
      'label_attributes' => array(
       'class' => 'control-label' 
      ), 
     ), 
    )); 

    // … add CSRF and submit elements … 
    $this->add(array(
     'type' => 'Zend\Form\Element\Csrf', 
     'name' => 'create_product_csrf', 
     'options' => array(
      'csrf_options' => array(
       'timeout' => 600 
      ) 
     ) 
    )); 

    $this->add(array(
     'name' => 'submit', 
     'type' => 'Submit', 
     'attributes' => array(
      'value' => 'Go', 
      'id' => 'submitbutton', 
      'class' => 'btn btn-primary' 
     ), 
    )); 
} 

/** 
* Get objectManager 
* 
* @return type 
*/ 
public function getObjectManager() 
{ 
    return $this->objectManager; 
} 

/** 
* Set objectManager 
* 
* @param ObjectManager $objectManager 
* @return \Cms\Form\ProductForm 
*/ 
public function setObjectManager(ObjectManager $objectManager) 
{ 
    $this->objectManager = $objectManager; 

    return $this; 
} 

/** 
* Should return an array specification compatible with 
* {@link Zend\InputFilter\Factory::createInputFilter()}. 
* 
* @return array 
*/ 
public function getInputFilterSpecification() 
{ 
    return array(
     'create_another_product' => array(
      'required' => FALSE, 
      'allow_empty' => TRUE, 
    )); 
} 
} 

我会显示两个字段集一个产品和一个用于相关实体:

class ProductFieldSet extends Fieldset implements InputFilterProviderInterface 
{ 

/** 
* @var ObjectManager 
* 
*/ 
protected $objectManager; 

/** 
* @var InputFilter 
* 
*/ 
protected $inputFilter; 

public function __construct(ObjectManager $objectManager) 
{ 
    parent::__construct('product'); 

    $this->setObjectManager($objectManager); 


    $this->setHydrator(new DoctrineEntity($this->getObjectManager()))->setObject(new Product()); 

    $this->addElements(); 
} 

public function addElements() 
{ 
    $this->add(array(
     'name' => 'id', 
     'type' => 'Hidden', 
    )); 

    $this->addLabelCode(); 
    $this->addArtist(); 
    $this->addTitle(); 
    $this->addDescription(); 
    $this->addPrice(); 
    $this->addHints(); 

    $this->add(array(
     'name' => 'subtitle', 
     'type' => 'Text', 
     'options' => array(
      'label' => 'Subtitle', 
     ), 
     'attributes' => array(
      'class' => 'form-control', 
     ), 
    )); 


    $this->add(array(
     'name' => 'amount', 
     'type' => 'Text', 
     'options' => array(
      'label' => 'Amount', 
     ), 
    )); 

    $date = new Date('instockdate'); 
    $date 
      ->setLabel('In Stock Date') 
      ->setAttributes(array(
       'min' => '2012-01-01', 
       'max' => '2200-01-01', 
       'step' => '1', // days; default step interval is 1 day 
    )); 



    $this->addGenre(); 
    $this->addLabel(); 
    $this->addType(); 
} 
// A lot of add methods 

/** 
* Add Type to the Cms\Form\ProductFieldSet 
*/ 
private function addType() 
{ 
    $typeFieldset = new TypeFieldSet($this->getObjectManager()); 
    $typeFieldset->setName('type'); 
    //$labelFieldset->setAttribute('required', TRUE); 
    //$labelFieldset->setAttribute('class', 'form-control'); 

    $typeFieldset->setLabel('Type'); 
    //$labelFieldset->setLabelAttributes(array('class' => 'control-label')); 

    $this->add($typeFieldset); 
} 
} 

而现在的TypeFieldSet

class TypeFieldSet extends Fieldset implements InputFilterProviderInterface 
{ 

/** 
* @var ObjectManager 
* 
*/ 
protected $objectManager; 

/** 
* @var InputFilter 
* 
*/ 
protected $inputFilter; 

/** 
* Construct Cms\Form\GenreFieldSet. 
* 
* @param ObjectManager $objectManager 
*/ 
public function __construct(ObjectManager $objectManager) 
{ 
    parent::__construct('type'); 

    $this->setObjectManager($objectManager); 

    $this->setHydrator(new DoctrineEntity($this->getObjectManager()))->setObject(new Type()); 

    $this->addElements(); 
} 

/** 
* Method responsible for adding elements to \Cms\Form\Fieldset. 
*/ 
public function addElements() 
{ 
    $this->add(array(
     'name' => 'name', 
     'type' => 'Zend\Form\Element\Text', 
     'attributes' => array(
      'required' => true, 
      'id' => 'name', 
      'class' => 'form-control', 
      'placeholder' => 'Enter type name' 
     ), 
     'options' => array(
      'label' => 'Name', 
      'label_attributes' => array(
       'class' => 'control-label' 
      ), 

     ), 
    )); 
} 
// Additional methods 
} 

不知何故,学说试图将所有相关实体添加为新实体,并且根据我输入的名称未找到与现有实体相关的实体。

任何人都可以帮我吗?

- 编辑

因此,实际上我没有相关实体的ID存在。控制器代码如下所示:

嗨,所以缺少ID,因为我使用名称来标识相关对象。我的控制器看起来是这样的:

// Get your ObjectManager from the ServiceManager 
    $objectManager = $this->getServiceLocator()->get('Doctrine\ORM 
    \EntityManager'); 

    // Create the form and inject the ObjectManager 
    $form = new CreateProductForm($objectManager); 

    // Create a new, empty entity and bind it to the form 
    $product = new Product(); 
    $form->bind($product); 

    if ($this->request->isPost()) 
    { 
     $form->setData($this->request->getPost()); 

     if ($form->isValid()) 
     { 

      $this->getProductService()->saveProduct($product); 

      $this->flashMessenger()->addSuccessMessage('Product ' . $product->getName() . ' saved'); 

       return $this->redirect()->toRoute('product'); 
     } 
     else 
     { 
      $this->flashMessenger()->addErrorMessage($form->getMessages()); 
     } 
    } 

    return new ViewModel(array(
     'product' => $product, 
     'form' => $form 
    )); 
} 

我应该得到相关的ID在控制器或者是有一个更微妙的方式做到这一点? 在官方示例https://github.com/doctrine/DoctrineModule/blob/master/docs/hydrator.md#a-complete-example-using-zendform中没有在控制器代码中获得ID。

+0

我认为你需要显示控制器代码(假设控制器是您实际使用表单保存/绑定实体的位置。 –

回答

1

我不能完全弄清楚你在这里发布的大量代码是通过什么字段/数据,而是使水合物从数据库中找到并使用现有实体,然后使用这些实体来水化新对象您需要传递与关联对象的标识符对应的字段。

因此,假设您想要创建一个新的Product与现有的Genre这意味着将genre_id传递到数据中。因此,像这样:

$hydrator = new DoctrineObject($objectManager); 

$data = array(
    "genre" => array(
     "genre_id" => 1 
    ) 
); 

$product = new Product(); 

$hydrator->hydrate($data, $product); 

在这个非常基本的代码示例水化将从Genre实体识别标识字段中使用保湿新Product之前要收集它。所以如果你在你的数据集中传递标识符字段,它应该可以工作。

DoctrineObject将不会收集任何使用非标识符字段的实体。因此,如果您想通过除标识符字段之外的任何字段,则假定您希望与新实体建立新关联,并且它将使用您传递的数据来为新相关实体提供保湿。

如果通过标识符字段是你在做什么,这是行不通的,那么请详细哪些数据是准确地传递解释...