Простая PDO-обертка

В настоящее время мое веб-приложение выполняет простые запросы: простые операции CRUD, подсчет, …

Несколько месяцев назад кто-то рекомендовал мне здесь написать простую оболочку PDO для этого (чтобы избежать написания try / catch, prepare (), execute () и т. Д. Каждый раз, когда запрос должен быть выполнен). Этот пример был показан (я внес некоторые изменения, чтобы использовать его в своем собственном проекте):

public function execute() { $args = func_get_args(); $query = array_shift($args); $result = false; try { $res = $this->pdo->prepare($query); $result = $res->execute($args); } catch (PDOException $e) { echo $e->getMessage(); } return $result; } 

Поскольку мне нужно выполнить больше операций (выполнение запросов, извлечение 1 записи, извлечение нескольких записей, подсчет результатов), я создал метод для всех этих:

  public function getMultipleRecords() { $args = func_get_args(); $query = array_shift($args); $records = array(); try { $res = $this->pdo->prepare($query); $res->execute($args); $records = $res->fetchAll(); } catch (PDOException $e) { echo $e->getMessage(); } return $records; } public function getSingleRecord() { $args = func_get_args(); $query = array_shift($args); $record = array(); try { $res = $this->pdo->prepare($query); $res->execute($args); $record = $res->fetch(); } catch (PDOException $e) { echo $e->getMessage(); } return $record; } public function execute() { $args = func_get_args(); $query = array_shift($args); $result = false; try { $res = $this->pdo->prepare($query); $result = $res->execute($args); } catch (PDOException $e) { echo $e->getMessage(); } return $result; } public function count() { $args = func_get_args(); $query = array_shift($args); $result = -1; try { $res = $this->pdo->prepare($query); $res->execute($args); $result = $res->fetchColumn(); } catch(PDOException $e) { echo $e->getMessage(); } return $result; } 

Как вы видите, большая часть кода такая же. Для каждого метода различаются только 2 строки кода: инициализация $ result (я всегда хочу вернуть значение, даже если запрос завершается с ошибкой) и выборки. Вместо того, чтобы использовать 4 метода, я мог бы написать только один из них и передать дополнительный параметр с типом действия. Таким образом, я мог бы использовать кучу операторов if / else оператора switch. Однако, я думаю, код может стать беспорядочным. Это хороший способ решить эту проблему? Если нет, то что было бы хорошим решением?

Вторая проблема, с которой я столкнулась (именно поэтому сейчас я работаю над этим классом), заключается в том, что я хочу использовать подготовленные операторы с помощью инструкции LIMIT SQL. Однако это невозможно сделать:

 $res = $pdo->prepare("SELECT * FROM table LIMIT ?"); $res->execute(array($int)); 

По какой-то причине переменная будет указываться (и, следовательно, запрос не будет выполнен), как описано здесь: https://bugs.php.net/bug.php?id=40740

Решение, похоже, использует bindValue () и использует тип данных int в качестве параметра: http://www.php.net/manual/de/pdostatement.bindvalue.php

Я мог бы переписать метод (ы), чтобы поддержать это, но мне также нужно будет использовать дополнительный параметр. Я не могу просто использовать $db->execute($sql, $variable1, $variable2); больше, поскольку мне нужно знать тип данных.

Каков наилучший способ решить эту проблему?

благодаря

    Как насчет создания класса с методами, которые вы можете связать (для ясности я удалил проверку ошибок):

     class DB { private $dbh; private $stmt; public function __construct($user, $pass, $dbname) { $this->dbh = new PDO( "mysql:host=localhost;dbname=$dbname", $user, $pass, array( PDO::ATTR_PERSISTENT => true ) ); } 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() { return $this->stmt->execute(); } public function resultset() { $this->execute(); return $this->stmt->fetchAll(); } public function single() { $this->execute(); return $this->stmt->fetch(); } } 

    Затем вы можете использовать его следующим образом:

     // Establish a connection. $db = new DB('user', 'password', 'database'); // Create query, bind values and return a single row. $row = $db->query('SELECT col1, col2, col3 FROM mytable WHERE id > ? LIMIT ?') ->bind(1, 2) ->bind(2, 1) ->single(); // Update the LIMIT and get a resultset. $db->bind(2,2); $rs = $db->resultset(); // Create a new query, bind values and return a resultset. $rs = $db->query('SELECT col1, col2, col3 FROM mytable WHERE col2 = ?') ->bind(1, 'abc') ->resultset(); // Update WHERE clause and return a resultset. $db->bind(1, 'def'); $rs = $db->resultset(); 

    Вы можете изменить метод bind чтобы принять массив или ассоциативный массив, если хотите, но я нахожу этот синтаксис совершенно ясным – он избегает необходимости создавать массив. Проверка типа параметра является необязательной, поскольку PDO::PARAM_STR работает для большинства значений, но должен знать о потенциальных проблемах при передаче нулевых значений (см. Комментарий в документации PDOStatement->bindValue ).