PDO dynamic queries with prepared statement

1k views Asked by At

I have a PDO class wrapper:

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();
        }
    }

My dynamic query is here:

        $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];

But this returns me an error:

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

My debug info is below:

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%
)

Question: Where is a bug? Thanks!

1

There are 1 answers

1
Your Common Sense On BEST ANSWER

Unfortunately, questions like "Please watch my code and tell me where is a bug" are sure offtopic on this site.

the only answer possible is to tell you how to debug your query and how to localize the problem.

Look, you have a query and parameters.

Try to run it with raw PDO. Does it work?
If not - try to take out your conditions (along with corresponding parameters) one by one. On which one it stopped? Can you reproduce the problem with this one?

Try to narrow your problem down as much as possible. that's the only way anyway.