Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在多对多关系中应用sql过滤器_Php_Doctrine Orm - Fatal编程技术网

Php 在多对多关系中应用sql过滤器

Php 在多对多关系中应用sql过滤器,php,doctrine-orm,Php,Doctrine Orm,我的项目中有多对多关系(用户角色、等级、用户角色等级)。但我也有一个要求,就是不要从数据库中删除任何数据。因此,我向表中添加了一个状态列,即连接两个表以创建多对多关系。现在我想继续 $userRole->getGrades() 仅获取unite表(用户角色等级)中没有状态“0”的记录。对于这些,我尝试使用sql过滤器 namespace Bis\MpBundle\Filter; use \Doctrine\ORM\Mapping\ClassMetaData; class UserR

我的项目中有多对多关系(用户角色、等级、用户角色等级)。但我也有一个要求,就是不要从数据库中删除任何数据。因此,我向表中添加了一个状态列,即连接两个表以创建多对多关系。现在我想继续

 $userRole->getGrades() 
仅获取unite表(用户角色等级)中没有状态“0”的记录。对于这些,我尝试使用sql过滤器

namespace Bis\MpBundle\Filter;
use \Doctrine\ORM\Mapping\ClassMetaData;

class UserRoleGradeFilter extends \Doctrine\ORM\Query\Filter\SQLFilter
{
    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
    {
        if("Bis\DefaultBundle\Entity\UserRoleGrade" == $targetEntity->name){

            return $targetTableAlias . '.status != 0';
        }

        return '';
    }
}
因此,它被称为Bis\DefaultBundle\Entity\UserRole,而不是Bis\DefaultBundle\Entity\UserRoleGrade Entity。有人有什么想法吗


或者你可能有其他想法,我怎么能做到呢?

我认为这是不可能的,因为它直接附加SQL。 即使您尝试SQL注入之类的方法:

return $targetTableAlias . '.status != 0)) LEFT join the_other_table ON  '
. $targetTableAlias . '.grades HAVING the_other_table.status = 0 ((';

它可能会在语句上崩溃,如
(())

您可以调用
$targetEntity->getAssociationMappings()['yourFieldName']
如果存在
joinTable
键,则表示您有
manytomy
关系。其中
yourFieldName
您的字段与
manytomy
关系

您可以从
doctor\ORM\Query\SqlWalker::getSQLTableAlias()
获取正确的表别名。 我用
debug\u backtrace
获得了
SqlWalker
,这不是一个优雅的解决方案,但我还没有找到更好的解决方案

/**
 * Get SqlWalker with debug_backtrace
 *
 * @return null|SqlWalker
 */
protected function getSqlWalker()
{
    $caller = debug_backtrace();
    $caller = $caller[2];

    if (isset($caller['object'])) {
        return $caller['object'];
    }

    return null;
}
my
addFilterConstraint
方法的完整实现

    public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
    if (empty($this->reader)) {
        return '';
    }

    // The Doctrine filter is called for any query on any entity
    // Check if the current entity is "pool aware" (marked with an annotation)
    $poolAware = $this->reader->getClassAnnotation(
        $targetEntity->getReflectionClass(),
        PoolAware::class
    );
    if (!$poolAware) {
        return '';
    }

    if (!$poolId = $this->getParameter('poolId')) {
        return '';
    }

    $fieldName = $poolAware->getFieldName();
    if (empty($fieldName)) {
        return '';
    }

    if (!$sqlWalker = $this->getSqlWalker()) {
        return '';
    }

    if (!isset($targetEntity->getAssociationMappings()[$fieldName])) {
        return '';
    }

    $mapping = $targetEntity->getAssociationMappings()[$fieldName];

    if (isset($mapping['joinColumns'])) {
        // oneToMany relation detected
        $table = $targetEntity->getTableName();
        $columnName = $mapping['joinColumns'][0]['name'];
        $dqlAlias = constant($targetEntity->getName() . '::MNEMO');
    } elseif (isset($mapping['joinTable'])) {
        // manyToMany relation detected
        $dqlAlias = constant($mapping['targetEntity'] . '::MNEMO');
        $component = $sqlWalker->getQueryComponent($dqlAlias);

        // Only main entity in query is interesting for us,
        // otherwise do not apply any filter
        if ($component['parent']) {
            return '';
        }
        $table = $mapping['joinTable']['name'];
        $columnName = $mapping['joinTable']['inverseJoinColumns'][0]['name'];
    } else {
        return '';
    }

    $tableAlias = ($sqlWalker instanceof BasicEntityPersister)
        ? $targetTableAlias // $repository->findBy() has been called
        : $sqlWalker->getSQLTableAlias($table, $dqlAlias);

    $query = sprintf('%s.%s = %s', $tableAlias, $columnName, $this->getConnection()->quote(poolId));

    return $query;
}
我们所有的理论模型都有MNEMO常量,它是模型的简单名称
Abc\Module\Model\Product
具有MNEMO
Product
。此MNEMO相当于存储库类中的
\u alias
。这就是为什么我们将此值应用于
$dqllais


您可以阅读的完整代码解释

您找到解决方案了吗?我正在尝试做一些类似的事情,但没有在解决方案上取得任何进展……我试图寻找解决方案,但没有找到。在我的过滤器的末尾,我只添加了一个子查询(在术语或性能上可能是个坏主意,但我得到了期望的结果)。