2012-04-01 88 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

相关问题