我有以下设置:
我有一个Product
条令对象和一些相关的条令实体。
/**
* Product
*
* @ORMTable(name="products")
* @ORMEntity(repositoryClass="EntitiesProductRepository")
*/
class Product
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORMColumn(name="artist", type="string", length=100, precision=0, scale=0, nullable=false, unique=false)
*/
private $artist;
/**
* @var string
*
* @ORMColumn(name="title", type="string", length=100, precision=0, scale=0, nullable=false, unique=false)
*/
private $title;
/**
* @var string
*
* @ORMColumn(name="subtitle", type="string", length=100, precision=0, scale=0, nullable=true, unique=false)
*/
private $subtitle;
/**
* @var string
*
* @ORMColumn(name="labelcode", type="string", length=100, precision=0, scale=0, nullable=false, unique=false)
*/
private $labelcode;
/**
* @var string
*
* @ORMColumn(name="description", type="string", length=100, precision=0, scale=0, nullable=true, unique=false)
*/
private $description;
/**
* @var string
*
* @ORMColumn(name="hints", type="text", precision=0, scale=0, nullable=true, unique=false)
*/
private $hints;
/**
* @var string
*
* @ORMColumn(name="price", type="decimal", precision=0, scale=2, nullable=false, unique=false)
*/
private $price;
/**
* @var integer
*
* @ORMColumn(name="amount", type="integer", precision=0, scale=0, nullable=true, options={"default" = 0}, unique=false)
*/
private $amount;
/**
* @var string
*
* @ORMColumn(name="image", type="string", length=100, precision=0, scale=0, nullable=true, unique=false)
*/
private $image;
/**
* @var DateTime
*
* @ORMColumn(name="instockdate", type="date", precision=0, scale=0, nullable=true, unique=false)
*/
private $instockdate;
/**
* @var boolean
*
* @ORMColumn(name="ownrelease", type="boolean", precision=0, scale=0, nullable=true, columnDefinition="BOOLEAN DEFAULT FALSE", unique=false)
*/
private $ownrelease;
/**
* @var EntitiesLabel
*
* @ORMManyToOne(targetEntity="EntitiesLabel", inversedBy="products")
* @ORMJoinColumns({
* @ORMJoinColumn(name="label_id", referencedColumnName="id", nullable=false)
* })
*/
private $label;
/**
* @var EntitiesGenre
*
* @ORMManyToOne(targetEntity="EntitiesGenre", inversedBy="products"))
* @ORMJoinColumns({
* @ORMJoinColumn(name="genre_id", referencedColumnName="id", nullable=false)
* })
*/
private $genre;
/**
* @var EntitiesType
*
* @ORMManyToOne(targetEntity="EntitiesType")
* @ORMJoinColumns({
* @ORMJoinColumn(name="type_id", referencedColumnName="id", nullable=false)
* })
*/
private $type;
/**
* @var EntitiesWebshop
*
* @ORMManyToOne(targetEntity="EntitiesWebshop", inversedBy="products")
* @ORMJoinColumns({
* @ORMJoinColumn(name="webshop_id", referencedColumnName="id", nullable=true)
* })
*/
private $webshop;
/**
* @var EntitiesSupplier
*
* @ORMManyToOne(targetEntity="EntitiesSupplier")
* @ORMJoinColumns({
* @ORMJoinColumn(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 EntitiesProduct
$this->add(array(
'type' => 'ZendFormElementCheckbox',
'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' => 'ZendFormElementCsrf',
'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 CmsFormProductForm
*/
public function setObjectManager(ObjectManager $objectManager)
{
$this->objectManager = $objectManager;
return $this;
}
/**
* Should return an array specification compatible with
* {@link ZendInputFilterFactory::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 CmsFormProductFieldSet
*/
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 CmsFormGenreFieldSet.
*
* @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 CmsFormFieldset.
*/
public function addElements()
{
$this->add(array(
'name' => 'name',
'type' => 'ZendFormElementText',
'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
}
不知何故,Doctrine试图将所有相关实体添加为新实体,而不是根据我输入的名称找到要关联的现有实体。
有人能帮我吗?
--编辑
所以实际上我没有相关实体的ID。控制器代码如下:
嗨,所以ID不见了,因为我用这个名字来识别相关的对象。我的控制器看起来像这样:
// Get your ObjectManager from the ServiceManager
$objectManager = $this->getServiceLocator()->get('DoctrineORM
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-使用zendform的完整示例控制器代码中没有获得id。
我无法完全弄清楚您在这里发布的大量代码中传递了哪些字段/数据,但要使DoctrineObject
水合器从数据库中找到并使用现有实体,并随后将这些实体用于新对象的水合,您需要传递与关联对象的标识符相对应的字段。
假设您想用现有的Genre
创建一个新的Product
,这意味着要在数据中传递genre_id
。这样的东西:
$hydrator = new DoctrineObject($objectManager);
$data = array(
"genre" => array(
"genre_id" => 1
)
);
$product = new Product();
$hydrator->hydrate($data, $product);
在这个非常基本的代码示例中,hydrator将识别来自Genre
实体的标识符字段,并在对新的Product
进行水合之前使用它来收集它。因此,如果您在数据集中传递标识符字段,它应该会起作用。
DoctrineObject
不会使用标识符字段以外的其他字段收集任何实体。因此,如果您要传递除标识符字段之外的任何字段,它会假设您想与新实体建立新的关联,并将使用您传递的数据来水合新的相关实体。
如果传递标识符字段是您正在做的事情,但它不起作用,那么请详细解释您正在传递的数据