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);
    }
}