使用预准备语句的PDO动态查询

时间:2013-09-04 09:25:35

标签: php mysql pdo prepared-statement dynamic-queries

我有一个PDO类包装器:

class DB {

        private $dbh;
        private $stmt;

        private $queryCounter = 0;

        public function __construct($user, $pass, $dbname) {

            $dsn = 'mysql:host=localhost;dbname=' . $dbname;

            $options = array(
                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
                PDO::ATTR_PERSISTENT => true
            );

            try {
                $this->dbh = new PDO($dsn, $user, $pass, $options);
            }
            catch (PDOException $e) {
                echo $e->getMessage();
                die();
            }
        }

        public function query($query) {
            $this->stmt = $this->dbh->prepare($query);
            return $this;
        }

        public function bind($pos, $value, $type = null) {

            if( is_null($type) ) {
                switch( true ) {
                    case is_int($value):
                        $type = PDO::PARAM_INT;
                        break;
                    case is_bool($value):
                        $type = PDO::PARAM_BOOL;
                        break;
                    case is_null($value):
                        $type = PDO::PARAM_NULL;
                        break;
                    default:
                        $type = PDO::PARAM_STR;
                }
            }

             $this->stmt->bindValue($pos, $value, $type);
             return $this;
        }

        public function execute($vars = array()) {
                $this->queryCounter++;

                if (isset($vars) && count($vars)) {
                    foreach ($vars as $k => $v ) {
                        $this->bind(($k+1), $v);
                    }
                }

                return $this->stmt->execute();
        }

        public function resultset($vars = array()) {
            $this->execute($vars);
            return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
        }

        public function single($vars = array()) {
            $this->execute($vars);
            return $this->stmt->fetch();
        }
    }

我的动态查询在这里:

        $per_page           = ($filter["show_by"] >= 25 && $filter["show_by"] <= 100) ? intval($filter["show_by"]) : 25; 
        $start          = intval($filter["page_id"]) ?  ($filter["page_id"] -1)*$per_page : 0;

        $sql_counter    = 'SELECT COUNT(*) count FROM `products` WHERE 1=1';
        $sql_result = 'SELECT * FROM `products` WHERE 1=1';

        $data = [];

        if (isset($filter["mode"]) != 'extra') {

            $sql_counter    .= ' AND `status` = :status';
            $sql_result     .= ' AND `status` = :status';

            $data[":status"] = 1;

        }

        if (intval($filter["category_id"])) {

            $sql_counter    .= ' AND FIND_IN_SET(:category_id, `cid`)';
            $sql_result     .= ' AND FIND_IN_SET(:category_id, `cid`)';

            $data[":category_id"] = $filter["category_id"];
        }       

        if (strlen($filter["search_by"]) > 0) {

            $search          = '%'.filter_var($filter["search_by"], FILTER_SANITIZE_STRING).'%';
            $sql_counter    .= ' AND `name` LIKE :search';
            $sql_result     .= ' AND `name` LIKE :search';

            $data[":search"] = $search;
        }   

        /*print_r($sql_counter);
        print_r($data);
        die();
        */

        $count  = $this->db->query($sql_counter)->single($data)[0];

但这会给我一个错误:

 PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens

我的调试信息如下:

SELECT COUNT(*) count FROM `products` WHERE 1=1 AND `status` = :status AND FIND_IN_SET(:category_id, `cid`) AND `name` LIKE :search

Array
(
    [:status] => 1
    [:category_id] => 7
    [:search] => %123%
)

问题:哪里有错误? 谢谢!

1 个答案:

答案 0 :(得分:3)

不幸的是,像“请看我的代码并告诉我哪里有错误”这样的问题在本网站上确实是非正式的。

唯一的答案可能是告诉您如何调试查询以及如何本地化问题。

看,你有一个查询和参数。

尝试使用原始PDO运行它。它有用吗?
如果不是 - 尝试逐个取出您的条件(以及相应的参数)。它停在哪一个?你能用这个重现这个问题吗?

尝试尽可能缩小问题范围。这是唯一的方法。