2012-04-01 111 views
3

我知道:這已經完成了死亡。但是,相信我,我一直在研究如何解決這個問題。我想要實現的是PDO MySQL數據庫封裝器,可以與PDO一起使用,我可以將它們合併到我的代碼中。我的主要問題來自兩個函數,特別是我試圖達到的參數的實際綁定。之所以我說兩個的功能與一個是相反的,儘管我努力了,但我一直無法發現哪個人正在嘗試這個問題。變量的我已經確認它不是變量,這是別的。不過,事實上,我得到這個錯誤首先意味着東西必須是錯誤的代碼。SQLSTATE [HY093]:無效的參數編號:參數未定義(PDO)

附錄A:fetch($table, $columns, $whereArgs)

此功能的目的是簡單地讀取行。這是通過接受要提取的行的表,以及爲了完成特定任務而需要的任何列和where子句來實現的。一旦參數被提交,一個或兩個循環被調用,動態地形成查詢。

public function fetch($table, $columns, $whereArgs) 
    { 
     if ($whereArgs === NULL && $columns === NULL) return false; 

     $select = "SELECT "; 
     $where = " WHERE "; 

     $iQuery = 0; 

     $sqlParams = array(); 

     $columnCount = count($columns) - 1; 

     foreach($whereArgs as $key => $value) 
     { 
      $paramKey = sprintf(':%s', $key); 

      $where .= sprintf("`%s`= %s", $key, $paramKey); 

      $sqlParams[ "{$paramKey}" ] = sprintf("%s", $value); 

      if ($iQuery <= $columnCount) 
      { 
       $select .= sprintf('`%s`', $columns[ $iQuery ]); 
       $select .= ', '; 
      } 
      else 
      { 
       $select .= ' '; 
      } 

      ++$iQuery; 
     } 

     if ($iQuery <= $columnCount) 
     { 
      for(; $iQuery < $columnCount; ++$iQuery) 
      { 
       if ($iQuery < $columnCount) 
       { 
        $select .= sprintf('`%s`', $columns[ $iQuery ]); 
        $select .= ', '; 
       } 
       else 
       { 
        $select .= ' '; 
       } 
      } 
     } 

     $select .= sprintf("FROM `%s`", $table); 

     $query = $select . $where; 

     return $this->doQuery($query, $sqlParams, TRUE, QueryType::Row); 
    } 

附件B:doQuery($query, $sqlParams, $return = FALSE, $queryType = QueryType::None)

這個功能比較簡單:它是所有綁定值和執行語句,並及時檢查哪種類型的返回(返回類型,它們要麼'row','column'或'all',由類QueryType指定,該類不在本期範圍內),然後返回所要求的內容。

protected function doQuery($query, $sqlParams, $return = FALSE, $queryType = QueryType::None) 
    { 
     $statement = $this->mConnection->prepare($query); 

     foreach($sqlParams as $param => $value) 
     { 
      $statement->bindValue($param, $value); 
     } 

     $statement->execute(); 

     if ($return) 
     { 
      switch($queryType) 
      { 
       case QueryType::Row: 
        return $statement->fetch(); 
       case QueryType::Column: 
        return $statement->fetchColumn(); 
       case QueryType::All: 
        return $statement->fetchAll(); 
       case QueryType::None: 
        return $statement; 
       default: 
        return false; 
      } 
     } 

    } 

附件C:test.php

這僅僅是一個小的測試腳本,我寫的測試數據庫。

$database = new Database('evolve_admin'); 

$res = $database->fetch(
    'evol_users', 
    array('user.id', 'user.email', 'user.firstname'), 
    array('user.email' => '[email protected]') 
); 


var_dump($res); 

其他意見

我瞭解到,有有毛病我的代碼,我只是失去了,究竟它可能是。就我的調試技巧而言,我已經有研究過這個問題了很多,看來這個錯誤很常見。我的主要目標是讓包裝工作,如果有人發現代碼本身有任何問題(包括特別是這個問題之外的問題),請告訴我。

對於任何人誰提供在這一個手:非常感謝你。

+0

根據綁定參數的數量檢查生成的SQL,然後找出數字不匹配的原因。 – Corbin 2012-04-01 03:59:32

+0

問題是隻有一個參數被綁定。我測試了通過並綁定參數的for循環。我也能夠輸出變量,它們看起來應該完全一樣。 – zeboidlund 2012-04-01 04:25:02

+0

不,問題是沒有參數被綁定(或者更具體地說,你有N個參數並且綁定了一些x使得x Corbin 2012-04-01 04:26:46

回答

4

我想你忘卻一些場所有:

$where .= sprintf("`%s`= %s", $key, $paramKey); 

您使用的$wher變量下一次是當你把它添加到$select之一。

如果不止一個其中arg的地方是:

WHERE `%s`= %s`%s`= %s`%s`= %s`%s`= %s`%s`= %s 

你沒有與你的SELECT一代的思想做了錯誤。 順便說一句,你有兩個相同的循環和測試你的選擇代if ($iQuery <= $columnCount)。一個在where循環和另一個在外面。有什麼用?

編輯:當然,我忘了指出爲什麼你有這個該死的錯誤: 它在

$sqlParams[ "{$paramKey}" ] = sprintf("%s", $value); 

您創建一個表,將看起來像:array ("{:akey}" => "avalue")(我認爲值作爲字符串。 你爲什麼使用大括號({}),它完全地更改密鑰名稱(應爲:keyname{:keyname}

編輯2: 心情好所以這裏曾是你取方法的簡化版本(。沒有測試,但應該做工精細)

/* 
* $whereArgs default value is an array, so you can call a select 
* without an empty array supplied if you does not have some where clause arguments 
* The separator is how the element will be binded alltogether in the where clause 
*/ 
public function fetch($table, $columns, $whereArgs = array(), $separator= 'AND') 
{ 
    /* We return false, if the columns variable is not set, or is not an array, 
    * or (if it is an array) does not contain anything 
    * or the $whereArgs is not and array (it would mean something bad have been given) 
    */ 
    if (false == isset($columns) || false == is_array($columns) 
      || 0 == count($columns) || false == is_array($whereArgs)) 
    { 
     return false; 
    } 

    $select = "SELECT"; 
    $from = " FROM `$table`"; 
    $where = " WHERE "; 

    /* SELECT generation */ 
    for ($columIt = 0; $columIt < count($columns); $columIt++) 
    { 
     $select .= " " . $columns[$columIt]; 
     // We check if we need to add a ',' 
     if ($columIt+1 < count($columns)) 
     { 
      $select .= ","; 
     } 
    } 

    /* WHERE clause generation */ 
    $sqlParams = array(); 
    $whereIt = 0; 
    foreach($whereArgs as $key => $value) 
    { 
     $stripedKey = preg_replace('/\\./', '_', $key); 
     $where .= " $key= :$stripedKey"; 
     $sqlParams[ ":$stripedKey" ] = "$value"; 
     // We check if we need to add a where separator 
     if ($whereIt +1 < count($whereArgs)) 
     { 
      $select .= " $separator"; 
     } 
     $whereIt++; 

    } 

    /* the generated where clause is only printed if $whereArgs 
    * is not an empty array 
    */ 
    $query = $select . $from . ((0<count($whereArgs))?$where:""); 

    return $this->doQuery($query, $sqlParams, TRUE, QueryType::Row); 
} 

編輯3: '' BTW沒有看到你的測試樣品,但PARAM名不能包含字符

編輯4: 沒看到你要跟解決它,我添加了一個pre_replace來替換子集中的'。'。 也擺脫「`」字符呼應鍵時,查詢將失敗,否則

`user.email`=:arg 

不招人喜歡=)

user.email=:arg or user.`email`=:arg 

首選(`)用於包括在特殊字符列名稱與以前一樣使用,列名稱與任何現有名稱都不匹配。

編輯5: 而不是剝離您的密鑰來創建您的參數和參數數組。你可以使用一個安全的方式是什麼,以防止誤導characheters的幽靈,通過採取$的優勢whereIt計數器:

$where .= " $key= :arg_$whereIt"; 
$sqlParams[ ":arg_$whereIt" ] = "$value"; 

問候

+0

編輯後添加爲什麼你有這個錯誤(忘記告訴xD) – grifos 2012-04-01 04:16:58

+0

是的,我欣賞幫助,但不幸的是,我仍然有我的var_dump()輸出相同的確切查詢: SELECT'user.id', 'user.email','user.firstname',FROM'evol_users' WHERE'user.email' =:user.email。 – zeboidlund 2012-04-01 04:23:14

+0

什麼返回var_dump或$ sqlParams? – grifos 2012-04-01 04:28:41

0

的問題是由於這樣的事實,每一個專欄中,我曾在我的測試數據庫有一個'。'在'用戶'和列的名稱之間。我通過用下劃線替換每個句點來解決問題,並且擺脫了錯誤。雖然由於某種原因查詢仍然無法正常工作,但我相信事情會很好。

所以,例如:

user.email = user_email

相關問題