2010-04-26 2 views
6

Я работаю с PHP PDO и у меня есть следующая проблема:Внимания: PDOStatement :: Execute(): SQLSTATE [HY093]: Неверный номер параметра: число связанных переменных не соответствует количеству жетонов в

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; 
    } 
} 

ответ

-2

так как вы сделали в петле $i+1 так count($options) будет равна последней $i+1, что делает дубликат binding.Try

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

$statement->bindValue(count($options)+1, $city->getId()); 
2

Похоже, вы пытаетесь построить длинную (?) Серию «или» сравнений: 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++ 
} 
1

У вас есть несоответствие между количеством связанных параметров и количеством привязок в 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); 
0

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

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

Вам необходимо привязать последний параметр к позиции 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 для исключения исключений при ошибке.

0

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

$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 
+0

Я не понимаю, если это ответ или просто комментарий к ОП.Не могли бы вы перефразировать, пожалуйста? – paqogomez

Смежные вопросы