带有Doctrine的Symfony 4-保存ManyToOne

问题描述 投票:0回答:1

我的symfony代码有问题:我的存储库更新方法

 /**
     * @param MenuModel $menu
     * @return MenuEntity|MenuModel
     * @throws RepositoryException
     */
    public function updateMenu(MenuModel $menu)
    {
        try {
            $transformedMenu = $this->menuTransformer->transform($menu);
            $transformedMenu = $this->getEntityManager()->merge($transformedMenu);
            $this->getEntityManager()->flush($transformedMenu);
            $this->getEntityManager()->detach($transformedMenu);

            return $this->menuTransformer->transform($transformedMenu);
        } catch (\Exception $e) {
            throw new RepositoryException($e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());
        }
    }

我的元素实体:

/**
 * Element.
 *
 * @ORM\HasLifecycleCallbacks
 * @ORM\Table(name="element")
 * @ORM\ChangeTrackingPolicy("DEFERRED_EXPLICIT")
 * @ORM\Entity(repositoryClass="CP\API\Repository\ElementRepository")
 */
class Element extends \CP\RestBundle\Model\Element
{
    use Traits\SystemObjectTrait;
    use Traits\ChannelsTrait;
    use Traits\PropertiesTrait;
    use Traits\WorkflowTrait;

    /**
     * @ORM\ManyToOne(targetEntity="Menu", inversedBy="contents")
     * @ORM\JoinColumn(name="menu_id", referencedColumnName="id")
     */
    protected $menu;

    /**
     * Element constructor.
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * @param int $id
     *
     * @return Element
     */
    public function setId(int $id): self
    {
        $this->id = $id;
        return $this;
    }

    /**
     * Update publication by modification when empty
     * Update status according to publication, unpublication and archiving
     *
     * @ORM\PrePersist()
     */
    protected function prePersist()
    {
        $this->updatePublication();
        $this->updateStatus();
    }

    /**
     * Update publication by modification when empty
     * Update status according to publication, unpublication and archiving
     *
     * @ORM\PreUpdate()
     */
    public function preUpdate()
    {
        $this->updatePublication();
        $this->updateStatus();
    }

    /**
     * Increases object version
     */
    public function increaseVersion()
    {
        ++$this->version;
    }


    /**
     * @return mixed
     */
    public function getMenu()
    {
        return $this->menu;
    }

    /**
     * @param mixed $menu
     */
    public function setMenu($menu): void
    {
        $this->menu = $menu;
    }


}

我的菜单实体

<?php

namespace CP\API\Entity;

use CP\API\Entity\Traits\TimestampableTrait;
use CP\Model\Configuration;
use CP\Model\Content;
use CP\Model\Language;
use CP\Model\MenuTranslation;
use CP\RestBundle\Model\Locator;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;


/**
 * @ORM\HasLifecycleCallbacks()
 * @ORM\Table(name="custom_menu")
 * @ORM\Entity(repositoryClass="CP\API\Repository\MenuRepository")
 */
class Menu
{
    use TimestampableTrait;

    /**
     * @var int
     *
     * @ORM\Id()
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;


    /**
     * @ORM\OneToMany(targetEntity="CP\API\Entity\Element",mappedBy="menu",cascade={"persist"})
     */
    protected $contents;

    public function __construct(Menu $parent = null)
    {
        $dateTime = new \DateTime();
        $this->creation = $dateTime;
        $this->modification === null && $this->setModification($dateTime);
        $this->contents = new ArrayCollection();
    }

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }


    /**
     * @param int $id
     */
    public function setId(int $id): void
    {
        $this->id = $id;
    }


    /**
     * @return ArrayCollection
     */
    public function getContents(): ArrayCollection
    {
        return $this->contents;
    }

    /**
     * @param ArrayCollection $contents
     */
    public function setContents(ArrayCollection $contents): void
    {
        $this->contents = $contents;
    }

    /**
     * @param Element $element
     * @return $this
     */
    public function addContent(Element $element): self
    {
        if (!$this->contents->contains($element)) {
            $this->contents[] = $element;
            $element->setMenu($this);
        }
        return $this;
    }

    /**
     * @param Element $element
     * @return $this
     */
    public function removeContent(Element $element): self
    {
        if ($this->contents->contains($element)) {
            $this->contents->removeElement($element);
            if ($element->getMenu() === $this) {
                $element->setMenu(null);
            }
        }
        return $this;
    }
}

我的菜单型号

<?php

namespace CP\Model;

use CP\RestBundle\Model\Element;
use CP\RestBundle\Model\Locator;
use CP\RestBundle\Model\Product;
use CP\RestBundle\Model\Traits\TimestampableTrait;

class Menu extends BaseModel
{

    /** @var Content[] */
    protected $content;

    /**
     * @return array|null
     */
    public function getContent(): ?array
    {
        return $this->content;
    }

    /**
     * @param Content[] $content
     */
    public function setContent(array $content): void
    {
        $this->content = $content;
    }

}

我的从模型到实体的转换器

public function transform($object)
{
     if ($object instanceof Menu) {
            $menuData = new MenuEntity();
            if ($object->getId())
                $menuData->setId($object->getId());


            if ($object->getContent() instanceof Content) {
                $contentEntity = new ContentEntity();
                $content = $object->getContent();

                $contentEntity->setId($content->getId());
                $menuData->addContent($this->attachToEntityManager($contentEntity));
            }

            return $menuData;
}

 private function attachToEntityManager($object)
    {
        try {
            $attachedObject = $this->entityManager->merge($object);
            return $attachedObject;
        } catch (ORMException $e) {
            throw new ModelTransformationException(sprintf('Model transformation error, object could not be attached to Entity Manager: %s in %s',
                $e->getMessage(), $e->getFile() . ':' . $e->getLine()));
        }
    }

[当我尝试保存数据时,我没有任何错误,但是在数据库上没有任何更改,即元素实体没有从关系中分配menu_id。我不知道怎么了,也许我不知道如何使用和保存OneToMany关系。

任何想法?

symfony doctrine
1个回答
0
投票

您能给我们更多代码执行情况的信息吗? MenuEntity的构造函数很奇怪,不使用$ parent,不使用布尔比较。为什么需要使用EntityManager的分离和合并方法-麦斯基

是的,我在这里看不到使用分离和/或合并的意义。通常,使用OneToMany关系时,您可以使用实体管理器并保持两个关系(刷新),并且您应该拥有一个具有OneToMany关系的实体。

我希望这会有所帮助,特别是这部分:https://symfony.com/doc/current/doctrine/associations.html#saving-related-entities

示例:

        // relates this product to the category
        $product->setCategory($category);

        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($category);
        $entityManager->persist($product);
        $entityManager->flush();
© www.soinside.com 2019 - 2024. All rights reserved.