mro*_*rok 5 php symfony doctrine-orm
我使用doctrine过滤器,最近注意到过滤器不适用于删除语句.我试图通过文档和谷歌挖掘,但神秘仍未解决.
例如,我有过滤器连接用户和公司所以每个选择查询,如:
$userRepo->find(12);
Run Code Online (Sandbox Code Playgroud)
并从中进行了修改
SELECT .... FROM user t0 WHERE t0.id = 12
成
SELECT .... FROM user t0 WHERE t0.id = 12 AND(t0.company_id ='6')
很酷,这就是我需要的.
困扰我的是删除语句似乎没有受到影响.有谁知道它是默认的doctrine架构还是我的配置错了?
过滤器
use Doctrine\ORM\Mapping\ClassMetaData;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Doctrine\Common\Annotations\Reader;
class CompanyAware extends SQLFilter
{
/**
* @var Reader
*/
protected $reader;
/**
* @param ClassMetaData $targetEntity
* @param string $targetTableAlias
*
* @return string
*/
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
$query = '';
$ann = 'Mrok\\PortalBundle\\Annotation\\CompanyAware';
$isAware = $this->reader->getClassAnnotation($targetEntity->getReflectionClass(), $ann);
if ($isAware) {
$id = $this->getParameter('id');
$query = sprintf('%s.company_id = %s', $targetTableAlias, $id);
}
return $query;
}
public function setAnnotationReader(Reader $reader)
{
$this->reader = $reader;
}
}
Run Code Online (Sandbox Code Playgroud)
由于 Doctrine Repositories 没有内置的 delete(id) 或 deleteBy(criteria) ,我假设您指的是 $em->remove($entity); 或 DQL。查看代码(见下文),在执行 SQL 之前,删除或级联删除都不会应用过滤器。该文档表明过滤器应应用于 DQL。
http://doctrine-orm.readthedocs.org/en/latest/reference/filters.html
/**
* Deletes a managed entity.
*
* The entity to delete must be managed and have a persistent identifier.
* The deletion happens instantaneously.
*
* Subclasses may override this method to customize the semantics of entity deletion.
*
* @param object $entity The entity to delete.
*
* @return void
*/
public function delete($entity)
{
$class = $this->class;
$em = $this->em;
$identifier = $this->em->getUnitOfWork()->getEntityIdentifier($entity);
$tableName = $this->quoteStrategy->getTableName($class, $this->platform);
$idColumns = $this->quoteStrategy->getIdentifierColumnNames($class, $this->platform);
$id = array_combine($idColumns, $identifier);
$types = array_map(function ($identifier) use ($class, $em) {
if (isset($class->fieldMappings[$identifier])) {
return $class->fieldMappings[$identifier]['type'];
}
$targetMapping = $em->getClassMetadata($class->associationMappings[$identifier]['targetEntity']);
if (isset($targetMapping->fieldMappings[$targetMapping->identifier[0]])) {
return $targetMapping->fieldMappings[$targetMapping->identifier[0]]['type'];
}
if (isset($targetMapping->associationMappings[$targetMapping->identifier[0]])) {
return $targetMapping->associationMappings[$targetMapping->identifier[0]]['type'];
}
throw ORMException::unrecognizedField($targetMapping->identifier[0]);
}, $class->identifier);
$this->deleteJoinTableRecords($identifier);
$this->conn->delete($tableName, $id, $types);
}
/**
* @todo Add check for platform if it supports foreign keys/cascading.
*
* @param array $identifier
*
* @return void
*/
protected function deleteJoinTableRecords($identifier)
{
foreach ($this->class->associationMappings as $mapping) {
if ($mapping['type'] !== ClassMetadata::MANY_TO_MANY) {
continue;
}
// @Todo this only covers scenarios with no inheritance or of the same level. Is there something
// like self-referential relationship between different levels of an inheritance hierarchy? I hope not!
$selfReferential = ($mapping['targetEntity'] == $mapping['sourceEntity']);
$class = $this->class;
$association = $mapping;
$otherColumns = array();
$otherKeys = array();
$keys = array();
if ( ! $mapping['isOwningSide']) {
$class = $this->em->getClassMetadata($mapping['targetEntity']);
$association = $class->associationMappings[$mapping['mappedBy']];
}
$joinColumns = $mapping['isOwningSide']
? $association['joinTable']['joinColumns']
: $association['joinTable']['inverseJoinColumns'];
if ($selfReferential) {
$otherColumns = (! $mapping['isOwningSide'])
? $association['joinTable']['joinColumns']
: $association['joinTable']['inverseJoinColumns'];
}
foreach ($joinColumns as $joinColumn) {
$keys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
}
foreach ($otherColumns as $joinColumn) {
$otherKeys[] = $this->quoteStrategy->getJoinColumnName($joinColumn, $class, $this->platform);
}
if (isset($mapping['isOnDeleteCascade'])) {
continue;
}
$joinTableName = $this->quoteStrategy->getJoinTableName($association, $this->class, $this->platform);
$this->conn->delete($joinTableName, array_combine($keys, $identifier));
if ($selfReferential) {
$this->conn->delete($joinTableName, array_combine($otherKeys, $identifier));
}
}
}
Run Code Online (Sandbox Code Playgroud)