数据库
首页 > 数据库> > PHP-SQLSTATE [HY093]:无效的参数编号:未定义参数(PDO)

PHP-SQLSTATE [HY093]:无效的参数编号:未定义参数(PDO)

作者:互联网

我知道:这已经死了.

但是,相信我,我已经研究了很长时间来解决这个问题.我想要实现的是一个与PDO一起使用的PDO MySQL数据库包装器,我可以将其合并到我的代码中.我的主要问题尤其来自两个函数,以及我要达到的参数的实际绑定.我陈述了两种功能而不是一种功能的原因是,尽管我付出了很多努力,但我仍无法找出哪个功能正在尝试解决此问题.我已将变量var_dumped确认为不是变量,而是其他变量.尽管如此,事实上我首先遇到了这个错误,这意味着代码一定有问题.

图表A:fetch($table,$columns,$whereArgs)

此功能的目的是简单地获取一行.这是通过接受要获取的行的表以及需要专门完成任务的任何列和子句来实现的.提交参数后,将调用一个或两个循环,以动态形成查询.

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' => 'test1234@test.com' )
);


var_dump( $res );

其他的建议

我了解到我的代码有问题,我只是迷失了确切的含义.就我的调试技能而言,我已经对这个问题进行了相当多的研究,并且看来该错误非常普遍.我的主要目标是使该包装器正常工作,如果有人发现代码本身有任何错误(包括特别是在此问题范围之外的错误),请告诉我.

对于任何对此有所帮助的人:非常感谢.

解决方法:

我认为您忘记了那里的一些空间:

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

下次使用$whervariable是将其附加到$select上.

如果更多,其中arg在哪里:

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

您没有用SELECT一代的思想来犯错.
顺便说一句,如果($iQuery< = $columnCount),则对选择的一代有两个相同的循环和测试.一个在where循环中,另一个在外面.有什么用? 编辑:当然,我忘了指出为什么会有这个异常错误:
在里面

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

您创建的表将如下所示:array(“ {:akey}” =>“ avalue”)(我认为该值是字符串.
为什么要使用大括号({}),它会完全更改键名(应为:keynamenot {: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没有看到您的测试样本,但是参数名称不能包含“.”.烧焦

编辑4:
没找到您解决的方法,我添加了一个pre_replace来替换“.”.在您的子集中.
在回显键时也要摆脱’`’字符,否则查询将失败

`user.email`=:arg

不喜欢=)

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

首选(`)用于在列名中包含特殊字符,因此像以前一样使用,该列名与任何现有名称都不匹配.

编辑5:
而不是剥离键来创建参数和参数数组.通过利用$whereIt计数器,您可以使用一种安全的方法来防止出现误导性的小人物:

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

问候

标签:parameterized,wrapper,mysql,php,pdo
来源: https://codeday.me/bug/20191101/1984101.html