nepster-web
@nepster-web

По какой причине при сохранении сущности с отношением one to many, не записывается id на связь?

Есть 2 сущности:
<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="products")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
 */
class Product
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var string
     *
     * @ORM\Column(name="name", type="string", length=100)
     */
    private $name;

    /**
     * @ORM\ManyToOne(targetEntity="Category", inversedBy="products", cascade={"ALL"})
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id", onDelete="CASCADE")
     */
    private $category;

    /**
     * @ORM\OneToMany(targetEntity="Image", mappedBy="product")
     */
    private $images;

    /**
     * Product constructor.
     */
    public function __construct()
    {
        $this->images = new ArrayCollection();
    }
    ...
}


<?php

namespace AppBundle\Entity;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Table(name="images")
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ImageRepository")
 */
class Image
{
    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Product", inversedBy="images", cascade={"ALL"})
     * @ORM\JoinColumn(name="product_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
     */
    private $product;

    ...
}


Тут все просто, у товара могут быть изображения.
Теперь есть следующий код, сохранения этого дела в хранилище:
$product = new Product();
        $product->setName('Новый товар 1');

        $category = new Category();
        $category->setName('preview_1');

        $product->setCategory($category);

        $image1 = new Image();
        $image2 = new Image();
        $image3 = new Image();

        $product->addImage($image1);
        $product->addImage($image2);
        $product->addImage($image3);

        $em = $this->getDoctrine()->getManager();

        $em->persist($category);

        $em->persist($image1);
        $em->persist($image2);
        $em->persist($image3);

        $em->persist($product);

        $em->flush();


И проблема заключается в том, что при сохранении изображений им не проставляется product_id. Я долго не мог понять в чем проблема, копи паст с доков не решал проблемы. Хотя отношение многие к одному работали как полагается.
Весь день провел в поиске проблемы и случайно набрел на следующую запись:

...
public function addImage(\AppBundle\Entity\Image $image)
    {
        $this->images[] = $image;

        $image->setProduct($this);

        return $this;
    }
...


Тоесть в сущности Product в метод addImage, необходимо добавить строку $image->setProduct($this);, вроде логично, все работает. Но я не нашел об этом никакого упоминания в доках и мело того, это не было включено при генерации схемы моей сущности с помощью команды:

php bin/console doctrine:generate:entities AppBundle/Entity/Product


Подскажите пожалуйста почему команда не генерирует полностью рабочий вариант, возможно я что-то упустил ?
  • Вопрос задан
  • 418 просмотров
Решения вопроса 2
prototype_denis
@prototype_denis
Symfony
symfony.com/doc/current/reference/forms/types/coll...

Нужно явно персистить обратную сторону. Менеджер ничерта не знает о ваших изображениях, когда к нему прилетает продукт.

Так же все подробности при работе с асоциациями описаны тут
docs.doctrine-project.org/projects/doctrine-orm/en...
Ответ написан
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
Картинкам не надо знать о продуктах. Минимизируйте количество двусторонних ассоциаций.

Так же почитайте про каскадные персисты.

p.s. Подобные вопросы следует удалять так как "легко гуглится" или просто достаточно прочитать документацию. Не ленитесь иначе все будет и дальше плохо.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы