Объекты данных PHP
This is a little late. but I’m old and slow.
Regarding Extending PDOStatement and PDO I found that sending the PDOExtended class by reference helps:
In the constructor after parent::__construct() :
$this->setAttribute(\PDO::ATTR_STATEMENT_CLASS,array(‘PDOStatementExtended’, [&$this]));>
And in
class PDOStatementExtended extends \PDOStatement
protected function __construct
(
\PDO &$PDO,
)
I wanted to extend PDO class to store statistics of DB usage, and I faced some problems. I wanted to count number of created statements and number of their executings. So PDOStatement should have link to PDO that created it and stores the statistical info. The problem was that I didn’t knew how PDO creates PDOStatement (constructor parameters and so on), so I have created these two classes:
/**
* PHP Document Object plus
*
* PHP Document Object plus is library with functionality of PDO, entirely written
* in PHP, so that developer can easily extend it’s classes with specific functionality,
* such as providing database usage statistics implemented in v1.0b
*
* @author Peter Pokojny
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/
class PDOp protected $PDO ;
public $numExecutes ;
public $numStatements ;
public function __construct ( $dsn , $user = NULL , $pass = NULL , $driver_options = NULL ) $this -> PDO = new PDO ( $dsn , $user , $pass , $driver_options );
$this -> numExecutes = 0 ;
$this -> numStatements = 0 ;
>
public function __call ( $func , $args ) return call_user_func_array (array(& $this -> PDO , $func ), $args );
>
public function prepare () $this -> numStatements ++;
$args = func_get_args ();
$PDOS = call_user_func_array (array(& $this -> PDO , ‘prepare’ ), $args );
return new PDOpStatement ( $this , $PDOS );
>
public function query () $this -> numExecutes ++;
$this -> numStatements ++;
$args = func_get_args ();
$PDOS = call_user_func_array (array(& $this -> PDO , ‘query’ ), $args );
return new PDOpStatement ( $this , $PDOS );
>
public function exec () $this -> numExecutes ++;
$args = func_get_args ();
return call_user_func_array (array(& $this -> PDO , ‘exec’ ), $args );
>
>
class PDOpStatement implements IteratorAggregate protected $PDOS ;
protected $PDOp ;
public function __construct ( $PDOp , $PDOS ) $this -> PDOp = $PDOp ;
$this -> PDOS = $PDOS ;
>
public function __call ( $func , $args ) return call_user_func_array (array(& $this -> PDOS , $func ), $args );
>
public function bindColumn ( $column , & $param , $type = NULL ) if ( $type === NULL )
$this -> PDOS -> bindColumn ( $column , $param );
else
$this -> PDOS -> bindColumn ( $column , $param , $type );
>
public function bindParam ( $column , & $param , $type = NULL ) if ( $type === NULL )
$this -> PDOS -> bindParam ( $column , $param );
else
$this -> PDOS -> bindParam ( $column , $param , $type );
>
public function execute () $this -> PDOp -> numExecutes ++;
$args = func_get_args ();
return call_user_func_array (array(& $this -> PDOS , ‘execute’ ), $args );
>
public function __get ( $property ) return $this -> PDOS -> $property ;
>
public function getIterator () return $this -> PDOS ;
>
>
?>
Classes have properties with original PDO and PDOStatement objects, which are providing the functionality to PDOp and PDOpStatement.
From outside, PDOp and PDOpStatement look like PDO and PDOStatement, but also are providing wanted info.
When using prepared statements there is no official PDO feature to show you the final query string that is submitted to a database complete with the parameters you passed.
Use this simple function for debugging. The values you are passing may not be what you expect.
//Sample query string
$query = «UPDATE users SET name = :user_name WHERE > ;
//Sample parameters
$params = [ ‘:user_name’ => ‘foobear’ , ‘:user_id’ => 1001 ];
function build_pdo_query ( $string , $array ) //Get the key lengths for each of the array elements.
$keys = array_map ( ‘strlen’ , array_keys ( $array ));
//Sort the array by string length so the longest strings are replaced first.
array_multisort ( $keys , SORT_DESC , $array );
foreach( $array as $k => $v ) //Quote non-numeric values.
$replacement = is_numeric ( $v ) ? $v : «‘ < $v >‘» ;
//Replace the needle.
$string = str_replace ( $k , $replacement , $string );
>
echo build_pdo_query ( $query , $params ); //UPDATE users SET name = ‘foobear’ WHERE/> ?>
PDO. Использование
В execute() все параметры приводятся к строкам (PDO::PARAM_STR).
Биндинг параметров
Задать параметрам значение:
$stmt->bindValue(':name', 'value', PDO::PARAM_STR); // именованные параметрами $stmt->bindValue(1, 'value', PDO::PARAM_STR); // не именованные (с 1)
Связать параметр с переменной (по ссылке):
$stmt->bindParam(':name', $name, PDO::PARAM_STR); $stmt->bindParam(1, $id, PDO::PARAM_INT);
Извлечение данных
Установить режим извлечения данных по умолчанию:
$success = $stmt->setFetchMode(PDO::FETCH_CLASS, 'ClassName', [/* Аргументы конструктора */]);
Режимы извлечения результата
PDO::FETCH_ASSOC Ассоциативный массив (алиас \PDO::FETCH_NAMED) PDO::FETCH_NUM Массив, индексированный номерами столбцов (с 0) PDO::FETCH_OBJ Простая структура (stdClass Object) с публичными свойствами PDO::FETCH_CLASS Объект заданного типа. Установит публичные свойства или вызовет __set() PDO::FETCH_FUNC Вернуть результат ф-ции, которой передаются все поля записи (fetchAll only) PDO::FETCH_UNIQUE Извлечь уникальные записи (по первой колонке, значение которой будет ключем) PDO::FETCH_LAZY Извлечь запись как PDORow Object (not fetchAll) PDO::FETCH_GROUP Массив значений, сгруппированных по значению N-й колонки PDO::FETCH_KEY_PAIR Вернуть массив ключ => значение (запрос должен вернуть только 2 колонки)
Комбинирование режимов
Извлечь все записи как ассоциативные массивы:
$stmt->fetchAll(PDO::FETCH_ASSOC);
Первое значение поля — ключ массива в который вложены остальные поля:
$stmt->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC|PDO::FETCH_UNIQUE);
Колонка всех записей как плоский массив:
$stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_NUM, 0);
Извлечь все значения первой колонки:
$stmt->fetchAll(PDO::FETCH_COLUMN, 0); // плоский массив значений колонки $stmt->fetchAll(PDO::FETCH_COLUMN|PDO::FETCH_UNIQUE, 3); // 1-е поле - ключ, 4-е - значение
Методы извлечения результата
Извлечение каждой следующей записи (как ассоциативного массив):
Получить следующую запись как stdObject:
$stmt->fetchObject('stdClass', $arr_args_for_constructor);
Возвращает значение указанного столбца последующей строки или false:
Внимание!
При использовании fetchColumn() для извлечения данных из результирующего набора невозможно получить значение другого столбца той же строки.
Подсчитать количество строк:
#PDO, #prepare statement, #DB, #ORM