将 QueryBuilder 与表达式一起使用时出现语义错误

Semantical error when using QueryBuilder with an expression

我在使用 expr() 方法函数从数据库中获取数据时遇到问题。我想获取 isPublic = trueobjectType = $objectTypeuser = $userobjectType = $objectType 的数据,无论 isPublic 的值是什么.

我收到这个错误:

[Semantical Error] line 0, col 76 near 'user-avatar)': Error: 'user' is not defined.

我在存储库中的代码:

    public function findByObjectType($objectType, $user)
    {
        $qb = $this->createQueryBuilder('s');

        return $qb->where($qb->expr()->andX(
                $qb->expr()->eq('s.isPublic', true),
                $qb->expr()->eq('s.objectType', $objectType)
            ))
            ->orWhere($qb->expr()->andX(
                $qb->expr()->eq('s.user', $user->getId()),
                $qb->expr()->eq('s.objectType', $objectType)
            ))
            ->getQuery()
            ->getResult();
    }

其中:$objectType = 'user-avatar'; $user = UserInterface

使用 $qb->expr()->eq() 时,您需要为查询提供准确的值。在这种情况下,您需要将查询更改为如下内容:

$qb->expr()->eq('s.objectType', '"' . $objectType .'"')

这种字符串将在数据库查询中被正确引用。顺便说一句,布尔值也是如此。将 true 转换为字符串将导致 1。这就是为什么您在这种情况下没有遇到错误。 false 但是会转换为空字符串,这会导致错误。

为了更好地理解发生了什么,下面是将 eq() 表达式转换为查询的代码部分:

 /**
 * @return string
 */
public function __toString()
{
    return $this->leftExpr . ' ' . $this->operator . ' ' . $this->rightExpr;
}

expr()->eq() 会将表达式视为文字,尝试按字面意义使用它们,因为它们出现在方法调用中。

作为 mentioned 库作者:

You are not using parameter binding. Expressions use string concatenation internally, so this outcome is actually expected.

在你的情况下,你应该做类似::

的事情
 return $qb->where($qb->expr()->andX(
        $qb->expr()->eq('s.isPublic', ':true'),
        $qb->expr()->eq('s.objectType', ':objectType')
    ))
    ->orWhere($qb->expr()->andX(
        $qb->expr()->eq('s.user', ':userId'),
        $qb->expr()->eq('s.objectType', ':objectType')
    ))

    ->setParameter('true', true)
    ->setParameter('userId', $user->getId())
    ->setParameter('objectType', $objectType)

    ->getQuery()
    ->getResult();

这样您的代码更易于阅读、更安全、更便携。