2010-04-26 181 views
6

我與PHP PDO的工作相匹配的令牌數量,我有以下問題:警告:PDOStatement對象::執行():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...。您可能會發現更容易將其替換爲:

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

$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 (?, ?, ?, ?, ?) 

,然後做的值與綁定您在綁定參數的數量與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()。將一組參數傳遞給​​比較容易。以下是我會寫這樣的功能:

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()和​​返回值,這將是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

我不明白,如果這是一個答案或只是一個對OP的評論。你能改說嗎? – paqogomez 2013-11-04 23:47:33

相關問題