【问题标题】:Too few parameters: the query defines 1 parameters but you only bound 0参数太少:查询定义了 1 个参数,但您只绑定了 0 个
【发布时间】:2017-06-07 12:31:05
【问题描述】:

Symfony 版本 3.2.8

我不确定是什么导致了这个错误,根据Doctrine Documentation setParameter 函数是否被正确使用?

破解密码:

public function getNewShipChoices($uid, $fid) {
        /*Identify ships all ready added in fleet and do not allow them to be added again*/
        $q2 = $this->createQueryBuilder('c')
                    ->select('DISTINCT (c2.shipId)')
                    ->join('AppBundle:ShipsFleet', 'c2')
                    ->where('c.userid = :uid')->setParameter('uid', $uid)
                    ->andWhere('c2.fleetId = :fid')->setParameter('fid', $fid);

        $query = $this->createQueryBuilder('c3');
        $query->where($query->expr()->notIn('c3.shipId', $q2->getDQL()))->andWhere('c3.userid = :uid')->setParameter('uid', $uid);

        return $query->getQuery()->getResult();
    }

我尝试的另一件事是对 setParameter 值进行硬编码,这会带来相同的错误消息

 ->where('c.userid = :uid')->setParameter('uid', 1)
                            ->andWhere('c2.fleetId = :fid')->setParameter('fid', 1);

工作代码: 用硬编码值替换 setParameter 而不是传入 1 和 1 的 2 个整数值。

 public function getNewShipChoices($uid, $fid) {
        $q2 = $this->createQueryBuilder('c')
                    ->select('DISTINCT (c2.shipId)')
                    ->join('AppBundle:ShipsFleet', 'c2')
                    ->where('c.userid = 1')
                    ->andWhere('c2.fleetId = 1');

        $query = $this->createQueryBuilder('c3');
        $query->where($query->expr()->notIn('c3.shipId', $q2->getDQL()))->andWhere('c3.userid = 1');

        return $query->getQuery()->getResult();
    }

我错过了一些非常明显的东西吗?

【问题讨论】:

  • 当我得到这个错误时,我的代码是正确的,删除​​了缓存并且它起作用了。

标签: php symfony doctrine-orm


【解决方案1】:

我认为实际问题是由学说的 ->getDQL 命令未通过参数值引起的。它通过预期的参数,但只在执行时对它们进行水合。

在您的示例中,您在已经设置 fid 参数后将一些 DQL 传递给选择,但不要在执行的查询中重新设置该参数,Doctrine 不知道该参数,因此会引发错误正如预期的那样。

解决办法是:

public function getNewShipChoices($uid, $fid) {
    /*Identify ships all ready added in fleet and do not allow them to be added again*/
    $q2 = $this->createQueryBuilder('c')
                ->select('DISTINCT (c2.shipId)')
                ->join('AppBundle:ShipsFleet', 'c2')
                ->where('c.userid = :uid')
                ->andWhere('c2.fleetId = :fid');

    $query = $this->createQueryBuilder('c3');
    $query->where($query->expr()->notIn('c3.shipId', $q2->getDQL()))
        ->andWhere('c3.userid = :uid')
        ->setParameter('uid', $uid)
        ->setParameter('fid', $fid);;

    return $query->getQuery()->getResult();
}

请注意,$q2 没有设置参数,因为在传递 DQL 时这些参数会被丢弃。

【讨论】:

    【解决方案2】:

    Doctrine 表达式 'notIn' 在第二个参数中接受数组值。您已提出查询。此外,您应该使用“setParameter”绑定参数以避免注入。 请试试这个。

    public function getNewShipChoices($uid, $fid) {
            $shipIds = $this->createQueryBuilder('c')
                        ->select('DISTINCT (c2.shipId)')
                        ->join('AppBundle:ShipsFleet', 'c2')
                        ->where('c.userid = 1')
                        ->andWhere('c2.fleetId = 1')
                        ->getQuery()
                        ->getResult();
    
            $query = $this->createQueryBuilder('c3');
            $query->where($query->expr()->notIn('c3.shipId', $shipIds))->andWhere('c3.userid = :UserId')->setParameter(":UserId", $uid);
    
            return $query->getQuery()->getResult();
        }
    

    【讨论】:

      【解决方案3】:

      为什么不尝试 setParameters 而不是 setParameter ?

      $q2 = $this->createQueryBuilder('c')
      ->select('DISTINCT (c2.shipId)')
      ->join('AppBundle:ShipsFleet', 'c2')
      ->where('c.userid = :uid')
      ->andWhere('c2.fleetId = :fid')
      ->setParameters(['fid'=> $fid,'uid'=> $uid]);
      

      【讨论】:

        【解决方案4】:

        对于正在寻找该问题的解决方案的人。

        在我的情况下,问题是在同一查询中使用 setParameter 和 setParameters。

        例如,我有这样的事情:

        if ($eventId) {
            $qb->andWhere("ec.event = :eventId");
            $qb->setParameter('eventId', $eventId);
        }
        
        if ($from && $to) {
            $qb
                ->andWhere($qb->expr()->between('ec.startDatetime', ':from', ':to'))
                ->setParameters([
                    'from' => $from,
                    'to' => $to,
                ]);
        }
        

        当我们使用 queryBuilder 并且我们首先调用 setParameter 然后在第二次调用 setParameters 时,它会覆盖使用 setParameter 定义的数据。

        所以对我来说,解决方案是:

        ->setParameters([
            'from' => $from,
            'to' => $to,
        ]);
        

        写:

         ->setParameter('from', $from)
         ->setParameter('to', $to) 
        

        【讨论】:

          【解决方案5】:

          试试这个将单引号添加到 '1'。

          ->where('c.userid = :uid')->setParameter('uid', '1')
                                  ->andWhere('c2.fleetId = :fid')->setParameter('fid', '1');
          

          【讨论】:

            猜你喜欢
            • 2019-01-30
            • 2020-12-12
            • 1970-01-01
            • 1970-01-01
            • 2015-03-10
            • 2020-10-25
            • 1970-01-01
            • 1970-01-01
            • 2018-03-23
            相关资源
            最近更新 更多