PDO Wrapper
Ik heb deze wrapper geschreven omdat ik niet echt fan ben van PDO constants en dat in de code constant te verwerken. Het is volledig backwards compatible met PDO alleen zijn er 3 methoden overschreven van PDO. Waaronder prepare, execute en query. Qua werking zijn ze hetzelfde alleen met ietsjes meer functionaliteit en automatische binding. Ook krijg je direct de statement variabel terug zodat je sommige code makkelijker kunt in-linen en dus geen stmt variable hoeft te zetten. Ik heb hem zo efficiƫnt mogelijk proberen te maken en over de tijd heen zal ik gerust nog wel wat meer functionaliteit toevoegen maar voor iemand die gewoon een simpele wrapper wil kan je deze gebruiken en aanpassen naar jouw behoeftes. Ik post hem ook hier zodat ik misschien nog wat input zou kunnen krijgen van jullie, eventuele verbeteringen. Bijvoorbeeld, ik zat er misschien ook nog aan te denken om yields te gebruiken over de fetch* methoden.
<?php
/**
* PHP PDO Wrapper for multiple databases.
*
* PHP version 5.5+
*
* LICENSE:
* Feel free to use this code however you please.
* I only ask to leave this comment as it is.
* Also, I'd appreciate a message if you use it
* and or have suggestions to improve it.
*
* @category Database Class
* @author Johan Kruse <johan dot kruse at gmail>
* @version 0.1
*/
class DatabaseException extends Exception{}
abstract class Database extends PDO{
public $sth;
abstract protected function sqlTableExists();
abstract protected function sqlSelectDatabase();
private function getDSN($driver, $multiarg){
return "$driver:" . implode(';', array_map(function($v, $k){return "$k=$v";}, $multiarg, array_keys($multiarg)));
}
private function getParamType($type){
switch($type){
case 'string': return parent::PARAM_STR;
case 'integer': return parent::PARAM_INT;
case 'boolean': return parent::PARAM_BOOL;
case 'NULL': return parent::PARAM_NULL;
case 'double': return parent::PARAM_STR;
case 'resource': return parent::PARAM_LOB;
default:
throw new DatabaseException("Unsupported variable type: '$type' parsed in query.");
}
}
public function prepare($sql, $options = array()){
$this->sth = parent::prepare($sql, $options);
return $this;
}
public function query($stmt){
return $this->sth = parent::query($stmt);
}
public function execute(){
for($i = 0; $i < func_num_args(); $i++){
if(($type = gettype(($var = func_get_arg($i)))) == 'array'){
foreach($var as $key => $val){
if($type = (gettype($key) == 'string')){
$this->sth->bindValue(($key[0] != ':') ? ":$key" : $key, $val, $this->getParamType($type));
} else {
throw new DatabaseException("Unsupported array index, expected named parameter.");
}
}
} else {
$this->sth->bindValue($i+1, $var, $this->getParamType($type));
}
}
$this->sth->execute();
return $this->sth;
}
public function fetchAssoc(){
return $this->sth->fetch(PDO::FETCH_ASSOC);
}
public function fetchBoth(){
return $this->sth->fetch(PDO::FETCH_BOTH);
}
public function fetchNum(){
return $this->sth->fetch(PDO::FETCH_NUM);
}
public function fetchObj(){
return $this->sth->fetch(PDO::FETCH_OBJ);
}
public function fetchLazy(){
return $this->sth->fetch(PDO::FETCH_LAZY);
}
public function tableExists($name){
return $this->prepare($this->sqlTableExists())->execute($name)->rowCount() > 0;
}
public function selectDatabase($name){
return $this->prepare($this->sqlSelectDatabase())->execute($name);
}
function __construct($username, $password, $dsn, $options){
if(in_array($driver = strtolower(get_class($this)), parent::getAvailableDrivers())){
$dsn = gettype($dsn) == 'array' ? $this->getDSN($driver, $dsn) : (string) $dsn;
if(gettype($options) == 'array'){
$options[parent::ATTR_EMULATE_PREPARES] = true;
$options[parent::ATTR_ERRMODE] = parent::ERRMODE_EXCEPTION;
try{
parent::__construct($dsn, $username, $password, $options);
} catch(PDOException $e){
throw new DatabaseException('Could not connect to the database server.', $e);
}
} else {
throw new DatabaseException('Expected an array of options.', $e);
}
} else {
throw new DatabaseException("Database driver '$driver' is not supported on this machine.'");
}
}
}
class MySQL extends Database{
protected function sqlTableExists(){
return 'SHOW TABLES LIKE ?';
}
protected function sqlSelectDatabase(){
return "USE ?";
}
function __construct($username, $password, $dsn, $options = array()) {
parent::__construct($username, $password, $dsn, $options);
}
}
class PostgreSQL extends Database{
function sqlTableExists(){
return "SELECT count(*) FROM pg_class WHERE relname=? AND relkind='r'";
}
function sqlSelectDatabase(){
throw new DatabaseException('PostgrSQL does not support database swapping, create a new link or select from "db.table".');
}
function __construct($username, $password, $dsn, $options = array()) {
parent::__construct($username, $password, $dsn, $options);
}
}
?>
<?php
try{
$db = new MySQL('user', 'pass', array('host' => 'localhost', 'port' => 3306, 'dbname' => 'mydb'));
//$db = new MySQL('user', 'pass', 'host=localhost;port=3306;dbname=mydb;', array(PDO::OPTION => 'value'));
$db->exec('SET GLOBAL general_log_file = "/var/log/mysql.log";');
$db->exec("SET GLOBAL general_log = 'ON';");
echo $db->tableExists('settings') ? ' yes' : ' no';
// single inline code. execute exepects any number of variables, arrays needs to be multi indexed with param names.
$db->prepare("select username, password FROM users WHERE username=?")->execute((string)$_POST['password'])->rowCount() == 1;
$db->prepare("select username, password FROM users WHERE username=:pass")->execute(array('pass' => (string) $_POST['password'])->rowCount() == 1;
// or normal usage, pass nothing in execute and use the sth variable as you normally would.
$db->prepare("select username, password FROM users WHERE username=:pass");
$db->sth->bindValue(':pass', $_POST['password']);
echo $db->execute()->rowCount();
$db->prepare("select * from settings")->execute();
while($row = $db->fetchAssoc()){ //fetchBoth, fetchObj, fetchNum, fetchLazy.
print_r($row);
}
$db->selectDatabase("otherdb");
// kill
$db = null;
} catch(PDOException $e){
echo $e->getMessage();
} catch(DatabaseException $e){
echo $e->getMessage();
} catch(Exception $e){
die($e->getMessage());
}
?>
Reacties
0