PDO声明我丢失了代币,但我没有——这有什么问题吗?


PDO states I am missing tokens, But I am not - what's wrong with this

所以我已经设法吐出(通过var_dump)以下内容:

// This is my whole select statement
string 'SELECT * FROM logs AS LOG WHERE ( LOG.DATE BETWEEN :startMonth AND :endMonth ) AND LOG.VALUE LIKE :filter ' (length=106)
// This is the database object (note the params)
object(Micro'Database)[1667]
  protected 'query' => string 'SELECT * FROM logs AS LOG WHERE ( LOG.DATE BETWEEN :startMonth AND :endMonth ) ' (length=79)
  protected 'params' => 
    array
      ':startMonth' => 
        object(DateTime)[1668]
          public 'date' => string '2014-06-01 00:00:00' (length=19)
          public 'timezone_type' => int 3
          public 'timezone' => string 'UTC' (length=3)
      ':endMonth' => 
        object(DateTime)[1671]
          public 'date' => string '2014-06-30 23:59:59' (length=19)
          public 'timezone_type' => int 3
          public 'timezone' => string 'UTC' (length=3)
      ':filter' => string '%"unit_id": 1030006431%' (length=23)

所以在查询中,我们看到我使用:startMonth, :endMonth:filter,然后在参数中,我们看到我设置了相同的变量。所有东西都应该在那里。但显然不是:

'SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens'

呃…不,所有的代币都在那里。让我们看一下代码

public static function findByWildCard($unitId=null, $messageType=null, $filter=null, $month) {
    $sqlSelect = 'SELECT * ' .
                    'FROM logs AS LOG '.
                    'WHERE ( LOG.DATE BETWEEN :startMonth AND :endMonth ) ';

    // Connect to lazarus
    $query = self::connectToLazarus();
    // Start of the specified month. Eg. 2013-01-01 00:00:00
    $startMonth = 'DateTime::createFromFormat('Y-m-d H:i:s', $month.' 00:00:00');
    // End of the specified month. Eg. 2013-01-31 11:59:59
    $endMonth = clone $startMonth;
    $oneMonth = 'DateInterval::createFromDateString('1 month');
    $oneSecond = 'DateInterval::createFromDateString('1 second');
    $endMonth->add($oneMonth)->sub($oneSecond);
    // Get the results from the query
    $query->setQuery($sqlSelect)
        ->setParameter('startMonth', $startMonth)
        ->setParameter('endMonth', $endMonth);
    if (!empty($filter)) {
        $sqlSelect .= 'AND LOG.VALUE LIKE :filter ';
        $query->setParameter('filter', '%'.$filter.'%');
    }
    var_dump($query->getResult()); exit;
}

怎么回事?

在将过滤器添加到查询字符串之前,您正在设置查询。

// Get the results from the query
$query->setQuery($sqlSelect)
    ->setParameter('startMonth', $startMonth)
    ->setParameter('endMonth', $endMonth);
if (!empty($filter)) {
    $sqlSelect .= 'AND LOG.VALUE LIKE :filter ';
    $query->setParameter('filter', '%'.$filter.'%');
}

您将查询设置为$sqlSelect,然后在设置查询后附加过滤器部分,但再也不会将查询设置为新值

有三个可能的原因会导致这样的问题

  1. 一个错字。大多数时候,你只是拼错了一些变量或占位符名称。
  2. 令牌数量确实与变量数量不匹配。重新计票。
  3. 当您在查询的几个地方使用具有相同名称的占位符时,非常罕见的情况。要解决这个问题,只需打开仿真模式。