开发者

Extending PDO Statement Class

Is it possible to extend PHP PDO statement class to add custom methods to it? This would be different from extending the base PDO class. If so,开发者_如何学C how would one go about doing it since the statement class is only returned when running queries through the PDO class?


You can set the class with PDO::setAttribute():

PDO::ATTR_STATEMENT_CLASS: Set user-supplied statement class derived from PDOStatement. Cannot be used with persistent PDO instances. Requires array(string classname, array(mixed constructor_args)).

Example:

$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, [Custom::class]);


This is answered by a user in the PHP Manual under 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;
    }
}

You can find his original answer by searching: 'smileaf' at this page: https://php.net/manual/en/book.pdo.php


This is my code to save the result of a select query into a text file as insert statement. I first extend the PDOStatement class to add the custom method saveResultAsInsertStatement:

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

}
?>

Then I extend the PDO class to set the attribute 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)));
    }

}
?>

So then, I can write:

<?php
$conn = new MyPDO(... PDO constructor parameters here ...);

$sql = ... your select statement here...

$conn->query($sql)->saveResultAsInsertStatement(... name of the file here ...);


?>


If you are using namespaces for your classes you need to add a backslash to your class string.

Without namespace:

$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Custom', array($pdo)));

With namespace:

$pdo->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('Namespace\Custom', array($pdo)));
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜