【发布时间】:2022-01-25 11:11:53
【问题描述】:
对于我当前的项目,我正在构建一个简单的 QueryBuilder 类。一切正常,除了与 mysqli 的 bindParam() 方法的参数绑定,我就是找不到错误。
代码和程序:
-
请求处理程序从我的用户模型中调用以下方法:
public function getPasshashByUsername($username) { $qb = new SelectQuery(); $qb->select(['passhash']) ->from($this->sourceName) ->where('nickname', $username); $stmt = $qb->build(); $resultset = $qb->execute($stmt); return $resultset->fetch_assoc()['passhash'] ?? null; } -
对于具有潜在参数的部分,SelectQuery 类的工作方式如下:
public function where($col, $val) { $this->aQueryParts['where'] = $this->addCondition('WHERE',$col, $val); return $this; } private function addCondition($type, $col, $val) { $sExpr = $type . ' '; $sType = ''; if ( is_int($val) || is_bool($val) ) { $sExpr .= '? = ' . $val; $sType .= 'i'; } elseif ( is_double($val) ) { $sExpr .= '? = ' . $val; $sType .= 'd'; } else { $sExpr .= '? LIKE \'' . $val . '\''; $sType .= 's'; } $this->sTypes .= $sType; $this->aParams[] = $col; return $sExpr; } -
现在 build() 方法开始起作用,参数将被绑定:
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(); if ( !$stmt = $this->con->prepare($this->sQuery) ) { $msg = 'Error while preparing statement: "' . $this->sQuery . '"'; Logger::send($msg); die(); } // make params by-ref $params = []; foreach ( $this->aParams as $param ) { $params[] = &$param; } // Start Marker 2 if ( !empty($this->sTypes) ) { if ( !$stmt->bind_param($this->sTypes, ...$params) ) { $msg = 'Failed to bind parameters to Query: "' . $this->sQuery . '"'; Logger::send($msg); die(); } } // End Marker 2 return $stmt; }
execute() 方法只是以通常的方式包装 mysqli execute()。没有抛出错误/异常,它只返回一个没有匹配的结果集。关于 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”块,但它没有改变任何东西。
【问题讨论】:
-
'nickname'怎么可能匹配'TestUser'?这两个是完全不同的字符串。 -
我不明白你为什么要使用 MySQLi。这只是 PDO 的几行代码。
-
@Dharman 昵称是 vwuser 中的 col 名称
-
它将值 'TestUser' 与 vwuser.nickname 的实际值进行比较,就像在标记 1 的工作查询中一样 -> "SELECT passhash FROM vwuser WHEREnickname LIKE 'TestUser'"
-
哦,好吧,我想我有点搞糊涂了 =D 休息时间