使用自己的postLoad事件侦听器时,Symfony2 Doctrine2 orphanRemoval不起作用

时间:2014-05-07 14:08:17

标签: symfony doctrine-orm

我有一个服务(产品),它有很多库存。当用户登录时,假设他只被分配到一个位置。这就是为什么我必须过滤数组集合,因此用户无法编辑其他位置的库存。库存数量通常很少。我有一个ServiceType表单,它有一个集合类型,可以编辑,添加和删除库存。

问题是..我只为Service实体设置了一个实体监听器,在从数据库加载后,执行postLoad方法,将过滤后的清单保存到数组集合中。在表单类型上,我只看到过滤后的,也看到了编辑工作,当我向集合添加新项目时,它也有效。当我点击集合项上的删除按钮并提交表单时,将调用removeInventory()方法并从集合中删除该项。但是当我坚持服务时,doctrine不会生成DELETE查询,并且不会从数据库中删除“已删除”库存。当我再次访问表单时,项目仍在列表中。但是,如果我不使用postLoad方法,那么所有内容(也都是删除)都有效。

评论此行

$service->setInventory($inventory->matching($criteria));

修复了不删除问题,但当然我得到了所有项目,而不仅仅是过滤后的项目。

广告资源映射:

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <entity name="Service\Bundle\RepairBundle\Entity\Inventory" table="inventory">

    <indexes>
      <index name="fk_inventory_location1_idx" columns="location_id"/>
      <index name="fk_inventory_service1_idx" columns="service_id"/>
    </indexes>

    <entity-listeners>
      <entity-listener class="Service\Bundle\RepairBundle\Entity\Listener\InventoryListener">
          <lifecycle-callback type="prePersist" method="prePersistHandler"/>
      </entity-listener>
    </entity-listeners>

    <id name="id" type="integer" column="id">
      <generator strategy="IDENTITY"/>
    </id>

    <field name="quantity"  type="integer"  column="quantity"   nullable="false"/>
    <field name="stock"     type="integer"  column="stock"      nullable="false"/>

    <many-to-one field="service" target-entity="Service\Bundle\RepairBundle\Entity\Service" inversed-by="inventory">
      <join-columns>
        <join-column name="service_id" referenced-column-name="id" nullable="false"/>
      </join-columns>
    </many-to-one>

    <many-to-one field="location" target-entity="Service\Bundle\UserBundle\Entity\Location" inversed-by="inventory">
      <join-columns>
        <join-column name="location_id" referenced-column-name="id" nullable="false"/>
      </join-columns>
    </many-to-one>

  </entity>
</doctrine-mapping>

服务映射

<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
  <entity name="Service\Bundle\RepairBundle\Entity\Service" table="service">

    <indexes>
      <index name="fk_service_account1_idx" columns="account_id"/>
    </indexes>

    <entity-listeners>
      <entity-listener class="Service\Bundle\RepairBundle\Entity\Listener\ServiceListener">
          <lifecycle-callback type="postLoad" method="postLoadHandler"/>
      </entity-listener>
    </entity-listeners>

    <id name="id" type="integer" column="id">
      <generator strategy="IDENTITY"/>
    </id>

    <field name="name"          type="string"   column="name"           length="255"                nullable="false"/>
    <field name="description"   type="text"     column="description"                                nullable="true"/>
    <field name="stockable"     type="boolean"  column="stockable"                                  nullable="false"/>

    <field name="value"         type="decimal"  column="value"          precision="15"  scale="4"   nullable="false"/>
    <field name="tax"           type="decimal"  column="tax"            precision="5"   scale="2"   nullable="false"/>
    <field name="unit"          type="string"   column="unit"           length="63"                 nullable="false"/>

    <one-to-many target-entity="Service\Bundle\RepairBundle\Entity\Inventory" mapped-by="service" field="inventory" fetch="LAZY" orphan-removal="true">
      <cascade>
          <cascade-persist/>
          <cascade-remove/>
      </cascade>
    </one-to-many>

    <one-to-many target-entity="Service\Bundle\RepairBundle\Entity\Price" mapped-by="service" field="priceList" fetch="LAZY" orphan-removal="true">
      <cascade>
          <cascade-persist/>
          <cascade-remove/>
      </cascade>
    </one-to-many>

    <many-to-one field="account" target-entity="Service\Bundle\UserBundle\Entity\Account">
      <join-columns>
        <join-column name="account_id" referenced-column-name="id" nullable="false"/>
      </join-columns>
    </many-to-one>

  </entity>
</doctrine-mapping>

服务实体监听器:

<?php
/**
 * Created by PhpStorm.
 * User: tomaz
 * Date: 06/05/14
 * Time: 15:33
 */

namespace Service\Bundle\RepairBundle\Entity\Listener;

use Doctrine\Common\Collections\Criteria;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;

use Service\Bundle\RepairBundle\Entity\Service;
use Service\Bundle\UserBundle\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\SecurityContext;

class ServiceListener
{
    protected $container;

    /** Doctrine entity listeners should have container injection, because of lazy loading other services, to avoid circular references
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function postLoadHandler(Service $service, LifecycleEventArgs $event)
    {
        if($service instanceof Service) # Should always be true
        {
            $inventory = $service->getInventory();

            if($this->getUser() instanceof User)
            {
                $criteria = Criteria::create()
                    ->where(Criteria::expr()->eq('location', $this->getUser()->getPrimaryLocation()))
                    ->orderBy(array('timeInsert' => Criteria::ASC));

                $service->setInventory($inventory->matching($criteria));
            }
        }
    }

    /**
     * @return User|null
     */
    private function getUser()
    {
        return $this->container->get('security.context')->getToken()->getUser();
    }
}

0 个答案:

没有答案