Самостоятельная ссылка на сущность Doctrine 2 ZF3 не обновляет все поля родительского элемента - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть самоссылающаяся сущность с родителями и детьми. Странно то, что когда я добавляю элементы формы (DoctrineModule ObjectSelect) для родительского и дочернего элементов в форму, некоторые другие поля родительского объекта не обновляются, когда я сохраняю объект. Дочерние сущности обновляются нормально.

В запросе на обновление родительского элемента нет тех полей, которые я хочу обновить. Это похоже на то, что доктрина больше не распознает изменения для родителя (стороны-владельца). Перед сохранением я получаю правильную сущность с фактическими изменениями из формы, но доктрина не обновляет измененные поля в запросе.

Когда я удаляю элементы формы для родительских и дочерних элементов в форме, все работает нормально, а родительская сущность обновляет / сохраняет все поля.

/**
 * @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;
}

1 Ответ

0 голосов
/ 04 мая 2018

Ответ основан на (и может еще измениться) на основе обсуждения в комментариях с ОП под вопросом.


Простой вариант использования: самоссылающаяся Doctrine Entity неправильно обновляет свойства объекта Entity, связанные с родителями / потомками, при сохранении.


ОП предоставлена ​​сущность.

Я предполагаю, что у вас есть настройка формы для этого объекта. Я также предполагаю, что это правильно настроено, поскольку вы не предоставили его после того, как его спросили (потому что, по правде говоря, это означало бы много кода). Тем не менее, допущение, что материал с кодом делает для многих ошибок, поэтому я упоминаю об этом здесь.

Таким образом, я предполагаю, что обработка вашей Формы в Контроллере может быть ошибочной. Для проверки воспользуйтесь следующей упрощенной функцией 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() ?: '',
    ];
}

Фабрика для класса с вышеперечисленным, измените, как вам нужно для ситуации

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...