使用 mysqli::bindParams() 时返回空结果集

Empty resultsset returned when using mysqli::bindParams()

对于我当前的项目,我正在构建一个简单的 QueryBuilder class。一切正常,除了与 mysqli 的 bindParam() 方法绑定的参数,我就是找不到错误。

代码和过程:

execute() 方法只是以通常的方式包装 mysqli execute()。没有 Error/Exception 被抛出,它只是 returns 一个没有匹配项的结果集。关于 XDebug,这些是调用 bind_params():

时的相关值
$this->sQuery = "SELECT passhash FROM vwuser WHERE ? LIKE 'TestUser'";
$this->sParams = "s";
$this->aParams = [ "nickname" ];

如果我在“标记 1”下方的行中取消注释查询字符串的硬编码分配并注释掉标记 2 的块(bind_params 的调用),一切正常,所以看起来连接本身是有效的。 在 php.net 阅读 bind_params 需要引用后,我插入了“make by-ref”块,但它没有改变任何东西。

你真的应该考虑学习 PDO 而不是 mysqli 或使用一些现有的数据库访问库。

您不能绑定列名。重点是您绑定数据。你正在做相反的事情。我建议去掉 addCondition 方法,因为它实际上没有任何意义,并且会导致代码中出现许多错误。相反,只需将参数直接传递给 bind_param 并使用 str_repeat() 作为类型。

以下是您的操作方法:

public function where($col, $val)
{
    $this->aQueryParts['where'] = 'WHERE '.$col. '=?';
    $this->aParams[] = $val;
    return $this;
}

public function build()
{
    if (isset($this->aQueryParts['from'])) {
        $sQuery = '';
        foreach ($this->aQueryParts as $part) {
            if (is_string($part)) {
                if (!empty($part)) {
                    $sQuery .= $part . ' ';
                }
                continue;
            }
            if (is_array($part)) {
                foreach ($part as $entry) {
                    if (!empty($entry)) {
                        $sQuery .= $entry . ' ';
                    }
                }
            }
        }
        $this->sQuery = $sQuery;
    // Marker 1
    //$this->sQuery = 'SELECT * FROM vwuser WHERE nickname LIKE \'TestUser\'';
    } else {
        Logger::send('You must at least call from() to get a valid query.');
        die();
    }

    $this->con = (new DatabaseAdapter())->connect();
    $stmt = $this->con->prepare($this->sQuery);
    // Start Marker 2
    if ($this->aParams) {
        $stmt->bind_param(str_repeat('s', count($this->aParams)), ...$this->aParams);
    }

    // End Marker 2
    return $stmt;
}

如您所见,我还删除了 if 语句。你真的应该考虑 enabling mysqli error reporting 而不是手动检查错误。

这是更正后的版本。 感谢@Dharman 给我提示。 错误是对行中问号位置的一些混淆:

$sExpr .= '? LIKE \'' . $val . '\'';

当然应该是:

$sExpr .= $col . ' LIKE ?';

所以addCondition()的修正版本是:

  private function addCondition($type, $col, $val) {
    $sExpr = $type . ' ';
    $sType = '';
    if ( is_int($val) || is_bool($val) ) {
      $sExpr .=  $col . ' = ?';
      $sType .= 'i';
    } elseif ( is_double($val) ) {
      $sExpr .=  $col . ' = ?';
      $sType .= 'd';
    } else {
      $sExpr .= $col . ' LIKE ?';
      $sType .= 's';
    }
    $this->sTypes .= $sType;
    $this->aParams[] = $val;
    return $sExpr;
  }