Предупреждение: PDOStatement :: execute (): SQLSTATE : Недопустимый номер параметра: количество связанных переменных не совпадает с числом токенов в

Я работаю с PHP PDO, и у меня есть следующая проблема:

Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /var/www/site/classes/enterprise.php on line 63 

Вот мой код:

  public function getCompaniesByCity(City $city, $options = null) { $database = Connection::getConnection(); if(empty($options)) { $statement = $database->prepare("SELECT * FROM `empresas` WHERE `empresas`.`cidades_codigo` = ?"); $statement->bindValue(1, $city->getId()); } else { $sql = "SELECT * FROM `empresas` INNER JOIN `prods_empresas` ON `prods_empresas`.`empresas_codigo` = `empresas`.`codigo` WHERE "; foreach($options as $option) { $sql .= '`prods_empresas`.`produtos_codigo` = ? OR '; } $sql = substr($sql, 0, -4); $sql .= ' AND `empresas`.`cidades_codigo` = ?'; $statement = $database->prepare($sql); echo $sql; foreach($options as $i => $option) { $statement->bindValue($i + 1, $option->getId()); } $statement->bindValue(count($options), $city->getId()); } $statement->execute(); $objects = $statement->fetchAll(PDO::FETCH_OBJ); $companies = array(); if(!empty($objects)) { foreach($objects as $object) { $data = array( 'id' => $object->codigo, 'name' => $object->nome, 'link' => $object->link, 'email' => $object->email, 'details' => $object->detalhes, 'logo' => $object->logo ); $enterprise = new Enterprise($data); array_push($companies, $enterprise); } return $companies; } } 

Related of "Предупреждение: PDOStatement :: execute (): SQLSTATE : Недопустимый номер параметра: количество связанных переменных не совпадает с числом токенов в"

Похоже, вы пытаетесь построить длинную (?) Серию «или» сравнений: if (x=1) or (x=2) or (x=3) etc... . if (x=1) or (x=2) or (x=3) etc... Вам может быть проще заменить его:

 $cnt = count($options); if ($cnt > 0) { $placeholders = str_repeat(', ?', $cnt - 1); $sql .= 'WHERE '`prods_empresas`.`produtos_codigo` IN (?' . $placeholders . ')'; } 

который, если бы было 5 вариантов, дал бы вам

  WHERE prods_empresas.produtos_condigo IN (?, ?, ?, ?, ?) 

А затем привязывайте значения к:

 $pos = 1; foreach ($options as $option) { $statement->bindValue($pos, $option->getId()); $pos++ } 

У вас есть несоответствие между количеством связанных параметров и количеством привязок в SQL. Двойной проверить, что количество ? и количество связанных параметров одинаково.

Кроме того, HY093 появится, если вы попытались связать параметр, который не существует:

 $stmt = "INSERT INTO table VALUES (:some_value)"; $stmt->bindValue(':someValue', $someValue, PDO::PARAM_STR); 

Смотрите :some_value не соответствует :someValue ! Исправление:

 $stmt = "INSERT INTO table VALUES (:some_value)"; $stmt->bindValue(':some_value', $someValue, PDO::PARAM_STR); 

Позиционные параметры в SQL начинаются с 1. Вы обрабатываете это путем привязки к позиции $i+1 в вашем цикле $ options.

Но затем вы привязываете последний параметр для cidades_codigo к count($options) позиции count($options) , который перезаписывает последний набор параметров в цикле $ options.

Вам нужно привязать последний параметр к count($options)+1 позиции count($options)+1 .


FWIW, вам вообще не нужно bindValue() . Легче просто передать массив параметров для execute() . Вот как я напишу эту функцию:

 public function getCompaniesByCity(City $city, $options = null) { $database = Connection::getConnection(); $sql = "SELECT * FROM `empresas` WHERE `empresas`.`cidades_codigo` = ?" $params = array(); $params[] = $city->getId(); if ($options) { $sql .= " AND `prods_empresas`.`produtos_codigo` IN (" . join(",", array_fill(1, count($options), "?") . ")"; foreach ((array)$options as $option) { $params[] = $option->getId(); } } $statement = $database->prepare($sql); echo $sql; $statement->execute($params); . . . 

Также не забудьте проверить возвращаемое значение prepare() и execute() , это будет false если есть ошибка, и вам нужно проверить это и сообщить об ошибке. Или иначе включить PDO для исключения исключений при ошибке.

Я столкнулся с этой проблемой из-за наличия дополнительных записей в массиве сопоставления именованных параметров, переданных в PDO :: Statement-> execute ()

 $args=array (":x" => 17 ); $pdo->prepare("insert into foo (x) values (:x)"); $pdo->execute($args); // success $args[':irrelevant']=23; $pdo->execute($args) // throws exception with HY093 

Так как вы сделали $i+1 в цикле, поэтому count($options) будет равен последнему $i+1 который делает дубликат привязки. Попробуйте

  foreach($options as $i => $option) { $statement->bindValue($i + 1, $option->getId()); } $statement->bindValue(count($options)+1, $city->getId());