Двунаправленные отношения «многие ко многим» с доктриной

0

У меня есть много-много двунаправленных отношений в Доктрине. Он связывает элементы с категориями. Проблема в том, что вначале я правильно отношу категорию к элементу, но когда я пытаюсь обновить категорию элемента, тогда она терпит неудачу с дублирующимся первичным ключом.

Это некоторые фрагменты кода, которые могут быть полезны:

/**
 * @ORM\Table(name="item")
 * @ORM\Entity(repositoryClass="SomeBundle\Entity\Repository\ItemRepository")
 *
 */
class Item
{
/**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="items",   cascade={"persist"})
     **/
    private $categories;
 public function __construct()
    {
        $this->categories = new \Doctrine\Common\Collections\ArrayCollection();
    }
/**
     * @param Item $item
     */
    public function addItem(Item $item)
    {
        $this->items[] = $item;
    }

а также

/**
 * Category
 *
 * @ORM\Table(name="category", indexes={@ORM\Index(name="category_parent", columns={"parent_id"})})
 * @ORM\Entity(repositoryClass="SomeBundle\Entity\Repository\CategoryRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Category
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
    * @ORM\ManyToMany(targetEntity="Item", mappedBy="categories", cascade={"persist"})
    * @ORM\JoinTable(name="item_category")
    **/
    private $items;

    public function __construct()
    {
        $this->items = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @param Category $category
     */
    public function addCategory(Category $category)
    {
        $this->categories[] = $category;
        $category->addItem($this);
    }

ОБНОВИТЬ

 public function saveItem(Request $request)
    {
        $editMode = false;
        $itemId = $request->request->get('item_id');

        if (isset($itemId) && $itemId > 0) {
            $editMode = true;
        }

        $itemName = $request->request->get('itemName');
        $itemShortName= $request->request->get('itemShortName');

        $itemRepo = $this->getItemRepository();
        $item = $itemRepo->find($itemId);

        // get last Item Id
        if (!$editMode) {
            $newItem = new Item();
            $newItemId = rand(1000, 6000); // TODO
            $newItem->setId($newItemId);
            $newItem->setSection('ar');
            // by default the item is inactive
            $newItem->setActive(0);
        }

        //store the Item Type
        $itemType = new ItemType();
        $itemType->setTypeId($request->request->get('itemType'));

        if (!$editMode) {
            $itemType->setItemId($newItemId);
        }

        // store the data into the ItemTranslation
        if (!$editMode) {
            $newItemTranslation = new ItemTranslation();
            $newItemTranslation->setItemId($newItemId);
            $newItemTranslation->setLanguageId('1');
            $newItemTranslation->setItemName($itemName);
            $newItemTranslation->ItemShortname($itemShortName);
            $newItemTranslation->setTimestampAdd(new \DateTime());
            $this->em->persist($newItemTranslation);
        }

        //assign the respective Categories to the item
        $selectedCategoriesIds = $request->request->get('itemCategories');
        $categoryRepo = $this->getCategoryRepository();

        if (count($selectedCategoriesIds) > 0) {
            foreach ($selectedCategoriesIds as $selectedCategoryId) {
                $category = $categoryRepo->find($selectedCategoryId);
                if (is_object($item)) { //TODO
                    $item->addCategory($category);
                    $category->addItem($item);

                } else {
                    $newItem->addCategory($category);
                    $category->addItem($newItem);
                }

                if (!$editMode) {
                    $this->em->persist($newItem);
                }
            }
        }

        $this->em->flush();
    }

Сообщение об ошибке

An exception occurred while executing 'INSERT INTO item_category (item_id, category_id) VALUES (?, ?)' with params [2117, 1]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2117-1' for key 'PRIMARY'

** ВТОРОЕ ОБНОВЛЕНИЕ **

Я добавил это if (is_object ($ item)) {$item-> removeExistingCategories(); } непосредственно перед:

if (count($selectedCategoriesIds) > 0) {
            foreach ($selectedCategoriesIds as $selectedCategoryId) {
                $category = $categoryRepo->find($selectedCategoryId);

и кажется, что он отлично работает, за исключением того, что теперь категории отображаются дважды в пользовательском интерфейсе, хотя таблица item_category была правильно заполнена.

Хорошо, последний вопрос, похоже, был отсортирован. Я допустил ошибку в итерациях itemsCategories. :)

  • 0
    Возможно, нам понадобится увидеть контроллер (или в другом месте проблема возникает). Что вы имеете в виду под update an item's category ?
  • 0
    @caCtus Спасибо за ответ. Я имею в виду, что я могу обновить категории, к которым принадлежит элемент.
Показать ещё 6 комментариев
Теги:
doctrine2

1 ответ

0

Попробуйте удалить каскад в категории Категория... вы должны сделать это только на стороне владельца отношений (пункт в вашем случае).

  • 1
    Спасибо за ответ, @Stev. Я удалил его, как предложено, и теперь я получаю ту же ошибку, когда пытаюсь сохранить ту же категорию и добавить новую к элементу. Но когда я удаляю ранее существующую категорию и добавляю элемент в другую категорию, то старая не удаляется, а новая сохраняется правильно. Надеюсь, это поможет.
  • 0
    Прочитайте эту статью symfony.com/doc/current/cookbook/form/form_collections.html . Особенно часть с Доктриной Постоянство от конца.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню