У меня есть самореферирующаяся сущность Product:

<?php
/** @Entity @Table(name="products") **/
class Product
{
    /** @Id @Column(type="integer") @GeneratedValue **/
    protected $id;
    /** @Column(type="string", nullable=true) **/
    protected $name;

    /**
     * @ManyToMany(targetEntity="Product", mappedBy="connectedBy", cascade={"all"})
     */
    protected $connectedWith;

    /**
     * @ManyToMany(targetEntity="Product", inversedBy="connectedWith", cascade={"all"})
     * @JoinTable(name="connection",
     *      joinColumns={@JoinColumn(name="product_id", referencedColumnName="id")},
     *      inverseJoinColumns={@JoinColumn(name="connected_product_id", referencedColumnName="id")}
     *      )
     */
    protected $connectedBy;

    public function __construct()
    {
        $this->connectedWith = new \Doctrine\Common\Collections\ArrayCollection();
        $this->connectedBy = new \Doctrine\Common\Collections\ArrayCollection();
    }
    public function getConnected()
    {
        return $this->connectedWith;
    }

    public function addConnection(Product $product)
    {
        $this->connectedWith->add($product);
        $product->connectedBy->add($this);
    }

    public function removeConnection(Product $product)
    {
        $this->connectedBy->removeElement($product);
        $this->connectedWith->removeElement($product);
    }
}

Затем я создал два продукта (идентификаторы 1 и 2) и соединение между ними:

mysql> select * from products;
+----+------+
| id | name |
+----+------+
|  1 | NULL |
|  2 | NULL |
+----+------+
2 rows in set (0.00 sec)

mysql> select * from connection;
+------------+----------------------+
| product_id | connected_product_id |
+------------+----------------------+
|          2 |                    1 |
+------------+----------------------+
1 row in set (0.01 sec)

Теперь я хочу удалить соединение с этим кодом:

$product1 = $entityManager->find('Product', 1);
$product2 = $entityManager->find('Product', 2);
$product1->removeConnection($product2);
$entityManager->persist($product1);
$entityManager->flush();

$product3 = $entityManager->find('Product', 1);
print count($product3->getConnected()) . "\n";

Как и ожидалось, в качестве результата код печатает 0. Но когда я смотрю в базу данных, запись о подключении все еще существует. В чем может быть причина, как это можно исправить?

Я уже пытался $entityManager->persist($product2), но безуспешно.

2
JSchirrmacher 7 Июл 2016 в 07:34
Вы пытаетесь удалить отношение другим способом? С помощью $ product2-> removeConnection ($ product1);
 – 
Ugo T.
7 Июл 2016 в 08:43
Забавно, но да - работает! @Ты получил. Вы представляете, почему?
 – 
JSchirrmacher
7 Июл 2016 в 09:09
Потому что это двусторонние отношения. С ManyToMany вы должны это сделать. Однако я не знаю, существует ли способ автоматически удалить все отношения (например, аннотацию или что-то в этом роде ...)
 – 
Ugo T.
7 Июл 2016 в 09:20

1 ответ

Лучший ответ

Я немного исследовал и сам нашел решение:

В моей функции removeConnection() есть ошибка: я удалил продукт из обоих списков, connectedBy и connectedWith, что неверно. Вместо этого я должен сделать это как в addConnection():

$this->connectedWith->removeElement($product);
$product->connectedBy->removeElement($this);
1
JSchirrmacher 9 Сен 2017 в 07:36