In PHP, how to set the default PDO class class?

Using PDO :: setAttribute , how do I specify the class name when setting PDO::ATTR_DEFAULT_FETCH_MODE to PDO::FETCH_CLASS .

This is the code I'm using. I would like to set it so that all my rows are returned as an instance of DB_Row :

 class DB_Row extends ArrayObject {} $db = new PDO('mysql:dbname=example;host=localhost', 'user', 'pass'); $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); $stmt = $db->query("SELECT * FROM `table` WHERE `id` = 1;"); $row = $stmt->fetch(); // I want a DB_Row by default! 

The above code PDOException because the class name DB_Row was not assigned.

 Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]: General error: No fetch class specified 

How can i do this?

Thanks in advance.

SOLUTION: I used fireeyedboy's answer. It worked best for my situation, as I already extended PDOStatement for logging purposes ...

 class DB extends PDO { public function __construct($host = null, $user = null, $pass = null, $db = null) { try { parent::__construct('mysql:dbname=' . $name .';host=' . $host, $user, $pass); $this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS); $this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DB_Query', array('DB_Row'))); } catch (PDOException $e) { die('Database Error'); } } } class DB_Query extends PDOStatement { private $class; protected function __construct ($class = 'DB_Row') { $this->class = $class; $this->setFetchMode(PDO::FETCH_CLASS, $this->class); } } class DB_Row extends ArrayObject { public function __set($name, $val) { $this[$name] = $val; } public function __get($name) { return $this[$name]; } } 
+6
source share
2 answers

Another type of hack would be to extend the PDOStatement , override its sampling methods and allow your PDO instance to use this as the default instruction class.

As an example, I will simply demonstrate the redefinition of fetch() 1 and leave fetchAll() , and what you have if you want to go this route:

 class Db_Row { } class PDOStatementWithClass extends PDOStatement { private $fetch_class; // PHP complained when I tried to make this public protected function __construct( $fetch_class = 'StdClass' ) { // internally set the fetch class for later use $this->fetch_class = $fetch_class; } // let $fetch_style default to PDO::FETCH_CLASS in stead of PDO::FETCH_BOTH public function fetch( $fetch_style = PDO::FETCH_CLASS, $cursor_orientation = PDO::FETCH_ORI_NEXT, $cursor_offset = 0 ) { // make sure we're really dealing with the correct fetch style if( $fetch_style == PDO::FETCH_CLASS ) { // then automatically set the fetch mode of this statement parent::setFetchMode( $fetch_style, $this->fetch_class ); } // go ahead and fetch, we should be good now return parent::fetch( $fetch_style, $cursor_orientation, $cursor_offset ); } } $db = new PDO( /* etc... */ ); // set default fetch mode to FETCH_CLASS $db->setAttribute( PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS ); // override what statement class to use, and provide constructor arguments (found out by trial and error) $db->setAttribute( PDO::ATTR_STATEMENT_CLASS, array( 'PDOStatementWithClass', array( 'Db_Row' ) ) ); 

This has the added benefit that you will only need to define PDO::FETCH_CLASS once in your application, and not in every request.


1) I am surprised that PHP did not complain about overriding the method signature, by the way.
+3
source

I think that it should return an instance of stdclass, so this will be an error, but you will have to look for it in the code for verification. will do if there is no accepted answer before.

What will work with PDO :: FETCH_CLASS | PDO :: FETCH_CLASSTYPE, and then specify the class name as the first column. Although this is a hack:

 $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); $stmt = $db->query("SELECT 'classname', * FROM `table` WHERE `id` = 1;"); 

EDIT: As the code promised here. The corresponding code is here http://lxr.php.net/xref/PHP_5_4/ext/pdo/pdo_stmt.c#940 Thus, setting to use fetch () is only possible with FETCH_CLASSTYPE. An alternative is to use PDOStatement :: fetchObject ()

+5
source

Source: https://habr.com/ru/post/898422/


All Articles