Doctrine 2 ZF3 自引用实体未更新 parent 的所有字段
Doctrine 2 ZF3 self referencing entity is not updating all fields of parent
我有一个带有 parent 和 children 的自引用实体。奇怪的是,当我将 parent 和 children 的表单元素(DoctrineModule ObjectSelect)添加到表单时, parent 实体的其他一些字段没有更新,当我坚持实体。 child 实体更新正常。
在 parent 的更新查询中,这些字段不是我要更新的。这就像学说不再承认 parent (拥有方)的变化。在坚持之前,我从表单中获得了具有实际更改的正确实体,但是学说不会更新查询中更改的字段。
当我删除表单中 parent 和 children 的表单元素时,一切正常,parent 实体 update/persist 所有字段。
/**
* @var string
*
* @Gedmo\Translatable
* @ORM\Column(type="text")
*/
private $teaser;
/**
* @var string
*
* @Gedmo\Translatable
* @ORM\Column(type="text")
*/
private $description;
/**
* One Category has Many Categories.
* @var Collection
* @ORM\OneToMany(targetEntity="Rental\Entity\Rental", mappedBy="parent")
*/
private $children;
/**
* Many Categories have One Category.
* @ORM\ManyToOne(targetEntity="Rental\Entity\Rental", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="houses_id", nullable=true, onDelete="SET NULL")
*/
private $parent;
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get teaser
*
* @return string
*/
public function getTeaser()
{
return $this->teaser;
}
/**
* Set teaser
*
* @param string $teaser
*/
public function setTeaser($teaser)
{
$this->teaser = $teaser;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set description
*
* @param string $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Add $child
* @param Collection $children
*/
public function addChildren(Collection $children)
{
foreach ($children as $child) {
$this->addChild($child);
}
}
/**
* @param Rental $child
* @return void
*/
public function addChild(Rental $child)
{
if ($this->children->contains($child)) {
return;
}
$child->setParent($this);
$this->children[] = $child;
}
/**
* Remove children
* @param Rental $children
*/
public function removeChildren(Collection $children)
{
foreach ($children as $child) {
$this->removeChild($child);
}
}
/**
* Remove child.
*
* @param \Rental\Entity\Rental $child
*
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeChild(Rental $child)
{
return $this->children->removeElement($child);
}
/**
* Get children.
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set parent.
*
* @param \Rental\Entity\Rental|null $parent
*/
public function setParent(Rental $parent = null)
{
$this->parent = $parent;
}
/**
* Get parent.
*
* @return \Rental\Entity\Rental|null
*/
public function getParent()
{
return $this->parent;
}
答案基于(并且可能仍会更改)基于与 OP 的评论中的讨论。
简单用例:自引用 Doctrine 实体在保存操作时未正确更新 parent/child 相关实体对象属性。
OP 提供实体。
我假设您为此实体设置了表单。我还假设它设置正确,因为您在被询问后没有提供它(因为,正确地,这意味着很多代码)。然而,假设有代码的东西会导致很多错误,这就是我在这里提到它的原因。
因此,我假设在控制器中处理您的表单可能有问题。要检查,请使用以下简化的 addAction
函数并试一试(下面的工厂代码)。
/**
* @var RentalForm
*/
protected $form;
/**
* @var ObjectManager
*/
protected $objectManager;
public function __construct(ObjectManager $objectManager, RentalForm $form)
{
$this->form = $form;
$this->objectManager = $objectManager;
}
public function addAction()
{
/** @var RentalForm $form */
$form = $this->getForm();
/** @var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$entity = $form->getObject();
$this->getObjectManager()->persist($entity);
try {
$this->getObjectManager()->flush();
} catch (\Exception $e) {
$message = sprintf(
'Was unable to save the data. Saving threw an error. <br />Code: %s. <br />Message: %s',
$e->getCode(),
$e->getMessage()
);
$this->flashMessenger()->addErrorMessage($message);
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
$this->flashMessenger()->addSuccessMessage(
$this->getTranslator()->translate('Successfully created object.')
);
// TODO replace vars with your own: return $this->redirect()->route($route, $routeParams);
}
$this->flashMessenger()->addWarningMessage(
'Your form contains errors. Please correct them and try again.'
);
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
Factory for class 以上,根据你的情况修改
class RentalControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var ObjectManager $objectManager */
$objectManager = $container->get(EntityManager::class);
/** @var FormElementManagerV3Polyfill $formElementManager */
$formElementManager = $container->get('FormElementManager');
/** @var RentalForm $form */
$form = $formElementManager->get(RentalForm::class);
return new RentalController($objectManager, $form);
}
}
我有一个带有 parent 和 children 的自引用实体。奇怪的是,当我将 parent 和 children 的表单元素(DoctrineModule ObjectSelect)添加到表单时, parent 实体的其他一些字段没有更新,当我坚持实体。 child 实体更新正常。
在 parent 的更新查询中,这些字段不是我要更新的。这就像学说不再承认 parent (拥有方)的变化。在坚持之前,我从表单中获得了具有实际更改的正确实体,但是学说不会更新查询中更改的字段。
当我删除表单中 parent 和 children 的表单元素时,一切正常,parent 实体 update/persist 所有字段。
/**
* @var string
*
* @Gedmo\Translatable
* @ORM\Column(type="text")
*/
private $teaser;
/**
* @var string
*
* @Gedmo\Translatable
* @ORM\Column(type="text")
*/
private $description;
/**
* One Category has Many Categories.
* @var Collection
* @ORM\OneToMany(targetEntity="Rental\Entity\Rental", mappedBy="parent")
*/
private $children;
/**
* Many Categories have One Category.
* @ORM\ManyToOne(targetEntity="Rental\Entity\Rental", inversedBy="children")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="houses_id", nullable=true, onDelete="SET NULL")
*/
private $parent;
public function __construct()
{
$this->children = new ArrayCollection();
}
/**
* Get teaser
*
* @return string
*/
public function getTeaser()
{
return $this->teaser;
}
/**
* Set teaser
*
* @param string $teaser
*/
public function setTeaser($teaser)
{
$this->teaser = $teaser;
}
/**
* Get description
*
* @return string
*/
public function getDescription()
{
return $this->description;
}
/**
* Set description
*
* @param string $description
*/
public function setDescription($description)
{
$this->description = $description;
}
/**
* Add $child
* @param Collection $children
*/
public function addChildren(Collection $children)
{
foreach ($children as $child) {
$this->addChild($child);
}
}
/**
* @param Rental $child
* @return void
*/
public function addChild(Rental $child)
{
if ($this->children->contains($child)) {
return;
}
$child->setParent($this);
$this->children[] = $child;
}
/**
* Remove children
* @param Rental $children
*/
public function removeChildren(Collection $children)
{
foreach ($children as $child) {
$this->removeChild($child);
}
}
/**
* Remove child.
*
* @param \Rental\Entity\Rental $child
*
* @return boolean TRUE if this collection contained the specified element, FALSE otherwise.
*/
public function removeChild(Rental $child)
{
return $this->children->removeElement($child);
}
/**
* Get children.
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getChildren()
{
return $this->children;
}
/**
* Set parent.
*
* @param \Rental\Entity\Rental|null $parent
*/
public function setParent(Rental $parent = null)
{
$this->parent = $parent;
}
/**
* Get parent.
*
* @return \Rental\Entity\Rental|null
*/
public function getParent()
{
return $this->parent;
}
答案基于(并且可能仍会更改)基于与 OP 的评论中的讨论。
简单用例:自引用 Doctrine 实体在保存操作时未正确更新 parent/child 相关实体对象属性。
OP 提供实体。
我假设您为此实体设置了表单。我还假设它设置正确,因为您在被询问后没有提供它(因为,正确地,这意味着很多代码)。然而,假设有代码的东西会导致很多错误,这就是我在这里提到它的原因。
因此,我假设在控制器中处理您的表单可能有问题。要检查,请使用以下简化的 addAction
函数并试一试(下面的工厂代码)。
/**
* @var RentalForm
*/
protected $form;
/**
* @var ObjectManager
*/
protected $objectManager;
public function __construct(ObjectManager $objectManager, RentalForm $form)
{
$this->form = $form;
$this->objectManager = $objectManager;
}
public function addAction()
{
/** @var RentalForm $form */
$form = $this->getForm();
/** @var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$entity = $form->getObject();
$this->getObjectManager()->persist($entity);
try {
$this->getObjectManager()->flush();
} catch (\Exception $e) {
$message = sprintf(
'Was unable to save the data. Saving threw an error. <br />Code: %s. <br />Message: %s',
$e->getCode(),
$e->getMessage()
);
$this->flashMessenger()->addErrorMessage($message);
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
$this->flashMessenger()->addSuccessMessage(
$this->getTranslator()->translate('Successfully created object.')
);
// TODO replace vars with your own: return $this->redirect()->route($route, $routeParams);
}
$this->flashMessenger()->addWarningMessage(
'Your form contains errors. Please correct them and try again.'
);
}
return [
'form' => $form,
'validationMessages' => $form->getMessages() ?: '',
];
}
Factory for class 以上,根据你的情况修改
class RentalControllerFactory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
/** @var ObjectManager $objectManager */
$objectManager = $container->get(EntityManager::class);
/** @var FormElementManagerV3Polyfill $formElementManager */
$formElementManager = $container->get('FormElementManager');
/** @var RentalForm $form */
$form = $formElementManager->get(RentalForm::class);
return new RentalController($objectManager, $form);
}
}