Расширение класса Statement PDO
Можно ли расширить класс операторов PHP PDO, чтобы добавить к нему специальные методы? Это будет отличаться от расширения базового класса PDO. Если да, то как это сделать, поскольку класс оператора возвращается только при выполнении запросов через класс PDO?
Ответы
Ответ 1
Вы можете установить класс PDO::setAttribute()
:
PDO:: ATTR_STATEMENT_CLASS: задайте класс операторов, созданный пользователем, полученный из PDOStatement. Не может использоваться с постоянными экземплярами PDO. Требуется массив (string classname, array (mixed constructor_args)).
Пример:
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Custom', array($pdo)));
Ответ 2
На это отвечает пользователь в Руководстве по PHP в PDO:
class Database extends PDO {
function __construct($dsn, $username="", $password="", $driver_options=array()) {
parent::__construct($dsn,$username,$password, $driver_options);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('DBStatement', array($this)));
}
}
class DBStatement extends PDOStatement {
public $dbh;
protected function __construct($dbh) {
$this->dbh = $dbh;
}
}
Вы можете найти его оригинальный ответ, выполнив поиск: 'smileaf' на этой странице: https://php.net/manual/en/book.pdo.php
Ответ 3
Это мой код, чтобы сохранить результат запроса select в текстовый файл в качестве инструкции insert.
Сначала я расширяю класс PDOStatement для добавления настраиваемого метода saveResultAsInertertatement:
<?php
class MyPDOStatement extends PDOStatement {
protected $pdo;
protected function __construct($pdo) {
$this->pdo = $pdo;
}
public function saveResultAsInsertStatement($filename) {
$result = '';
$columnData = $this->fetchAll(PDO::FETCH_ASSOC);
if ($columnData != null) {
$fieldCount = count($columnData[0]);
$rowsCount = count($columnData);
$columnsName = array_keys($columnData[0]);
$result = "INSERT INTO %s ( \n";
$result .= join(",\n", $columnsName);
$result .= ") VALUES\n";
$r = 0;
foreach ($columnData as $row) {
$result .= "(";
$c = 0;
foreach ($row as $key => $field) {
$result .= $this->pdo->quote($field);
$result .= ( ++$c < $fieldCount) ? ', ' : '';
}
$result .= ")";
$result .= ( ++$r < $rowsCount) ? ',' : '';
$result .= "\n";
}
}
$f = fopen($filename, "w");
fwrite($f, $result);
fclose($f);
}
}
?>
Затем я расширяю класс PDO, чтобы установить атрибут PDO:: ATTR_STATEMENT_CLASS
<?php
class MyPDO extends PDO {
public function __construct(... PDO constructor parameters here ... ) {
parent::__construct( ... PDO construct parameters here ...);
$this->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement', array($this)));
}
}
?>
Итак, я могу написать:
<?php
$conn = new MyPDO(... PDO constructor parameters here ...);
$sql = ... your select statement here...
$conn->query($sql)->saveResultAsInsertStatement(... name of the file here ...);
?>
Ответ 4
Если вы используете пространства имен для ваших классов, вам нужно добавить обратную косую черту в строку класса.
Без пространства имен:
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Custom', array($pdo)));
С пространством имен:
$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Namespace\Custom', array($pdo)));