Я использую фильтры доктрины и недавно заметил, что фильтры не применяются для удаления операторов. Я пытался разобраться с документацией и Google, но тайна остается нерешенной.
Например, у меня есть фильтр, который соединяет пользователя с компанией, поэтому каждый запрос на выбор:
$userRepo->find(12);
и изменяется от
SELECT …. FROM user t0 WHERE t0.id = 12
в
SELECT …. FROM user t0 WHERE t0.id = 12 AND (t0.company_id = '6')
круто, вот что мне нужно.
Меня беспокоит то, что заявления о стирании, по-видимому, не затронуты. Кто-нибудь знает, является ли это доктриной архитектуры по умолчанию, или моя конфигурация неверна?
Фильтр
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; } }
Поскольку Doctrine Repositories не имеет идентификатора delete (id) или deleteBy (критерии) как встроенного, я предполагаю, что вы ссылаетесь либо на $ em-> remove ($ entity); или DQL. Если вы посмотрите на код (см. Ниже), ни Remove, ни каскад не удалите соответствующие фильтры перед выполнением 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)); } } }