我有一个服务(产品),它有很多库存。当用户登录时,假设他只被分配到一个位置。这就是为什么我必须过滤数组集合,因此用户无法编辑其他位置的库存。库存数量通常很少。我有一个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();
}
}