Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/237.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 Doctrine2 QueryBuilder没有明确匹配任何内容_Php_Symfony_Doctrine Orm_Abstract Class_Query Builder - Fatal编程技术网

Php Doctrine2 QueryBuilder没有明确匹配任何内容

Php Doctrine2 QueryBuilder没有明确匹配任何内容,php,symfony,doctrine-orm,abstract-class,query-builder,Php,Symfony,Doctrine Orm,Abstract Class,Query Builder,我使用的是Doctrine 2.4,我有一个抽象基类,它包含如下方法: protected function getBaseQueryBuilder($type) { switch ($type) { case self::TYPE_1; return $this->em->createQueryBuilder()->...lots of clauses...; case self::TYPE_2;

我使用的是Doctrine 2.4,我有一个抽象基类,它包含如下方法:

protected function getBaseQueryBuilder($type) {
    switch ($type) {
        case self::TYPE_1;
            return $this->em->createQueryBuilder()->...lots of clauses...;
        case self::TYPE_2;
            return $this->em->createQueryBuilder()->...lots of clauses...;
        /* many more types... */
        case self::TYPE_N;
            return /* want to return a query builder for the empty set */
    }
}
有几个从这个基类继承的子类,每个子类从几个地方调用这个方法。然后,在执行查询生成器之前,它们使用其他特定于类的子句扩展返回的查询生成器。但是,对于
类型_N
,任何行都不能匹配

当然,一种解决方案是为
$type==type\N
返回null,让每个调用方检查
null
,如果是,则不执行任何操作。但是,如果我能返回一个查询生成器,它将永远不会匹配任何东西,并且查询甚至不会命中数据库,那就更好了。这将大大简化许多调用方站点


有什么方法可以做到这一点吗?

你为什么要这样做?我想说的是,您不应该创建一个昂贵的
QueryBuilder
对象,只是为了在以后调用
getResult()
时从中获取
null

我建议您重新设计您的解决方案,也许可以在拉取
getBaseQueryBuilder
方法和从查询生成器获得实际结果之间添加一个额外的方法。例如:

protected function getBaseQueryBuilder($type) {
    switch ($type) {
        case self::TYPE_1;
            return $this->em->createQueryBuilder()->...lots of clauses...;
        case self::TYPE_2;
            return $this->em->createQueryBuilder()->...lots of clauses...;
        case self::TYPE_N;
            return null;
    }
}

protected function getResultFromBaseQueryBuilder() {
    $type = $this->getType(); // get your type
    $queryBuilder = $this->getBaseQueryBuilder($type);
    if( $queryBuilder === null ){
        return /* empty result set so for example null, [] or new ArrayCollection(); */
    }
    return $queryBuilder->getResult();
}
您也可以直接在该方法中检查类型:

protected function getBaseQueryBuilder($type) {
    switch ($type) {
        case self::TYPE_1;
            return $this->em->createQueryBuilder()->...lots of clauses...;
        case self::TYPE_2;
            return $this->em->createQueryBuilder()->...lots of clauses...;
    }
}

protected function getResultFromBaseQueryBuilder() {
    $type = $this->getType(); // get your type
    if( $type === self:TYPE_N ){
        return /* empty result set so for example null, [] or new ArrayCollection(); */
    }
    $queryBuilder = $this->getBaseQueryBuilder($type);
    return $queryBuilder->getResult();
}

换句话说,与其制作一个包含
getBaseQueryBuilder
方法的公共接口,不如制作一个包含返回结果的方法的接口。(我建议您调用方法
getResult
,而不是
getResultFromBaseQueryBuilder
,我只是用它来澄清示例)

Acme\Doctrine\TypeQuery

Acme\Doctrine\TypeQueryBuilder

然后,在您的
getBaseQueryBuilder
调用中,您可以根据提供的类型添加子句或返回
TypeNQueryBuilder

protected function getBaseQueryBuilder($type)
{
    $queryBuilder = $this->em->createQueryBuilder();

    switch ($type) {
        case self::TYPE_1:
            $queryBuilder
                ->yadaYadaYada(....)
            ;
            break;
        case self::TYPE_2:
            $queryBuilder
                ->yadaYadaYada(....)
            ;
            break;
        case self::TYPE_N:
            return new TypeNQueryBuilder($this->em);
    }

    return $queryBuilder;
}
在界面相同的情况下,您只能使用

$this
    ->getBaseQueryBuilder($type)
    ->andWhere(...)
    ->addOrderBy(...)
    ->getQuery()
    ->getOneOrNullResult();

。。根据给定的类型,它要么正确地构建查询,要么在最后一分钟退出并返回您的
null
结果。

我理解构建一个昂贵的对象以在最后不返回任何内容是浪费的。然而,在我看来,您的解决方案似乎不支持我所描述的我需要的东西:几个子类将获得这样的查询生成器,然后在执行之前向其添加更多子句。我看不出您的解决方案如何实现这一点,因为构建了查询生成器并立即执行其查询。子类的作用在哪里?基于你在评论中给我的一点信息,很难给你一个建议。例如,您可以为您的服务创建一个
addClause
addExpression
方法,但我觉得可能有更好的方法来实现您的目标。也许你可以问另一个问题,在那里你可以添加更多的细节来解释你的用户案例?您还可以在子类内部检查是否得到一个
QueryBuilder
实例,并简单地忽略您有
TYPE\u N
的情况(因此没有
QueryBuilder
,向永远不会执行的查询添加子句没有多大意义).我需要的用例已在原始问题中描述。那么,您能否更具体地说明丢失了哪些信息?是的,我可以检查子类,正如我在原始问题中已经提到的。这个问题特别是关于不这样做,因为那将需要编写更多的代码。@jlh否决我的答案不会激励我花更多的时间来帮助你。我否决它是因为它不适用于我在原始问题中描述的用例。我认为这是一个公平的理由,这就是投票的目的。如果你不想在这上面花更多的时间,我理解。我目前正在尝试Qoopmao的解决方案。我喜欢这个解决方案。它甚至可以扩展为覆盖
和where()
orderBy()
等,以使这些操作更加便宜。我将尝试实现它,并看看它是如何运行的。我认为大多数方法,如
和where
innerJoin
,等等,都会做一些事情,然后调用
add
,这样您就可以覆盖它,只返回
$this
,并省去很多工作。
protected function getBaseQueryBuilder($type)
{
    $queryBuilder = $this->em->createQueryBuilder();

    switch ($type) {
        case self::TYPE_1:
            $queryBuilder
                ->yadaYadaYada(....)
            ;
            break;
        case self::TYPE_2:
            $queryBuilder
                ->yadaYadaYada(....)
            ;
            break;
        case self::TYPE_N:
            return new TypeNQueryBuilder($this->em);
    }

    return $queryBuilder;
}
$this
    ->getBaseQueryBuilder($type)
    ->andWhere(...)
    ->addOrderBy(...)
    ->getQuery()
    ->getOneOrNullResult();