Сохранение коллекции после удаления элементов

#php #doctrine-orm #zend-framework2

#php #doctrine-orm #zend-фреймворк2

Вопрос:

У меня есть 3 сущности доктрины:

  • Продукт
  • Магазин
  • ProductStore

Мне нужно иметь форму, которая позволяет управлять связями между ними с помощью коллекций форм Zend.

Добавление конечного редактирования работает хорошо, но удаление не сохраняется в базе данных. Другими словами, необходимые элементы удаляются из коллекции, но это не отражается в базе данных.

Вот ProductsController:

 <?php
class ProductsController extends AbstractActionController
{
    public function linkAction()
    {
        $request = $this->getRequest();

        $id = (int)$this->params()->fromRoute('id', null);

        $em = $this->getEntityManager();

         $formManager = $this->getServiceLocator()->get('FormElementManager');
         $form = $formManager->get('ProductLinkForm');

        $item = $em->find('ApplicationEntityProduct', $id);
        $form->bind($item);

        if ($this->request->isPost()) {
            $form->setData($this->request->getPost());

            if ($form->isValid()) {
                $em->persist($item);
                $em->flush();

                return $this->redirect()->toRoute(...);
            }
        }

        return new ViewModel(array(
            'form' => $form,
            'item' => $item,
        ));
    }
}
 

Набор полей:

 class ProductLinkFieldset extends Fieldset
{
    protected $objectManager;

    public function __construct(ObjectManager $objectManager)
    {
        parent::__construct('product_link_fieldset');
        $this->objectManager = $objectManager;
    }

    public function init()
    {
        $this->setHydrator(new DoctrineHydrator($this->objectManager))
            ->setObject(new Product());

        $this->add(array(
            'type'    => 'ZendFormElementCollection',
            'name'    => 'productStores',
            'options' => array(
                'count' => 0, // minimum elements count
                'should_create_template' => true,
                'allow_add' => true,
                'allow_remove' => true,
                'target_element' => array(
                    'type' => 'ProductStoreFieldset',
                ),      
            )
        ));
     }
 }
 

Product Сущность является:

 /**
 * Product
 *
 * @ORMTable(name="Product")
 * @ORMEntity
 */
class Product
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORMColumn(name="name", type="string", precision=0, scale=0, nullable=false, unique=false)
     */
    private $name;

    /**
     * @var DoctrineCommonCollectionsCollection
     *
     * @ORMOneToMany(targetEntity="ApplicationEntityProductStore", mappedBy="product", cascade={"persist"})
     */
    private $productStores;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->productStores = new ArrayCollection();
    }

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

    /**
     * Add productStores
     *
     * @param Collection $productStores
     */
    public function addProductStores(Collection $productStores)
    {
        foreach ($productStores as $productStore) {
            $productStore->setProduct($this);
            $this->productStores->add($productStore);
        }
    }

    /**
     * Remove productStores
     *
     * @param Collection $productStores
     */
    public function removeProductStores(Collection $productStores)
    {
        foreach ($productStores as $productStore) {
# if I uncomment this, there will be an error when persisting the entity:
# An exception occurred while executing 
# 'UPDATE product_store SET product_id = ? WHERE id = ?' with params [null, 4]: 
# Column can not be null.
//          $productStore->setProduct(null);

            $this->productStores->removeElement($productStore);
        }
        return $this;
    }
}
 

и ProductStore сущность:

 /**
 * ProductStore
 *
 * @ORMTable(name="product_store")
 * @ORMEntity
 */
class ProductStore
{
    /**
     * @var integer
     *
     * @ORMColumn(name="id", type="integer", precision=0, scale=0, nullable=false, unique=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string
     *
     * @ORMColumn(name="url", type="string", precision=0, scale=0, nullable=false, unique=false)
     */
    private $url;

    /**
     * @var ApplicationEntityProduct
     *
     * @ORMManyToOne(targetEntity="ApplicationEntityProduct", inversedBy="productStores", cascade={"persist","remove"})
     * @ORMJoinColumns({
     *   @ORMJoinColumn(name="product_id", referencedColumnName="id", nullable=false)
     * })
     */
    private $product;

    /**
     * @var ApplicationEntityStore
     *
     * @ORMManyToOne(targetEntity="ApplicationEntityStore", inversedBy="storeProducts")
     * @ORMJoinColumns({
     *   @ORMJoinColumn(name="store_id", referencedColumnName="id", nullable=false)
     * })
     */
    private $store;

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

    /**
     * Set product
     *
     * @param ApplicationEntityProduct $product
     * @return ProductStore
     */
    public function setProduct(ApplicationEntityProduct $product = null)
    {
        $this->product = $product;
        return $this;
    }

    /**
     * Get product
     *
     * @return ApplicationEntityProduct 
     */
    public function getProduct()
    {
        return $this->product;
    }

    /**
     * Set store
     *
     * @param ApplicationEntityStore $store
     * @return ProductStore
     */
    public function setStore(ApplicationEntityStore $store = null)
    {
        $this->store = $store;
        return $this;
    }

    /**
     * Get store
     *
     * @return ApplicationEntityStore 
     */
    public function getStore()
    {
        return $this->store;
    }
}
 

Итак, проблема в том, что удаленные элементы все еще находятся в базе данных, несмотря на то, что они удаляются из коллекции перед сохранением.

Ответ №1:

Это то, что мне было нужно: http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html#orphan-removal

Проблема решена.