Waarom een wrapper over PDO heen is omdat ik:
- van korte inline codes hou.
- beter compatibility met andere drivers.
- .. de PDO constants echt bagger vind.
Waar het fout gaat is in de function Database->execute(...).
De type variable word herkend in de switch case, dan moet er een waarde aan de statement gekoppeld worden en dat gebeurd dus niet.
Het ergste van deze situatie is dat "tableExists" werkte toen dat ik de execute method strakker ging maken.
Zelf denk ik dat het te maken heeft dat execute() eerder word aangeroepen dan prepare, alleen als ik elke functie een nummer echo in de volgorde dat ze uitgevoerd moeten worden klopt het wel.
SQL LOG:
150527 9:02:51 1376 Connect root@localhost on mydb
1376 Query SET GLOBAL general_log_file = "/var/log/mysql.log"
/usr/sbin/mysqld, Version: 5.5.43-0ubuntu0.14.10.1 ((Ubuntu)). started with:
Tcp port: 3306 Unix socket: /var/run/mysqld/mysqld.sock
Time Id Command Argument
1376 Query SET GLOBAL general_log = 'ON'
1376 Prepare SHOW TABLES LIKE ':table'
1376 Execute SHOW TABLES LIKE ':table' <<--- ':table' zou veranderd moeten zijn in 'settings'
1376 Close stmt
1376 Quit <?php
class DatabaseException extends Exception{}
abstract class Database extends PDO{
private $sth;
abstract function sqlTableExists();
abstract function sqlSelectDatabase();
private function getDSN($driver, $multiarg){
return "$driver:" . implode(';', array_map(function($v, $k){return "$k=$v";}, $multiarg, array_keys($multiarg)));
}
public function prepare($stmt, $options = array()){
$this->sth = parent::prepare($stmt, $options);
return $this;
}
public function query($stmt){
return $this->sth = parent::query($stmt);
}
public function execute($stmt = null){
try{
if(is_array($stmt)){
foreach($stmt as $k => $v){
if(gettype($k) == 'string'){
$k = ($k[0] != ':') ? ":$k" : $k;
switch(gettype($v)){
case 'string':
// hier gaat het fout.. als het goed is.
// $k = :table
// $v = settings
$this->sth->bindValue($k, $v, PDO::PARAM_STR);
break;
case 'integer':
$this->sth->bindValue($k, $v, PDO::PARAM_INT);
break;
case 'boolean':
$this->sth->bindValue($k, $v, PDO::PARAM_BOOL);
case 'NULL':
$this->sth->bindValue($k, $v, PDO::PARAM_NULL);
break;
case 'resource':
$this->sth->bindValue($k, $v, PDO::PARAM_LOB);
break;
case 'double':
$this->sth->bindValue($k, (string)$v, PDO::PARAM_STR);
break;
default:
throw new DatabaseException('Unsupported variable type parsed in query.');
break;
}
} else {
throw new DatabaseException('Only named parameters are allowed.');
}
}
}
try{
$this->sth->execute();
return $this->sth;
} catch(PDOException $e){
throw $e;
}
} catch(DatabaseException $e){
throw $e;
}
}
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($table){
// deze functie word aangeroepen.
return $this->prepare($this->sqlTableExists())->execute(array('table'=>$table))->rowCount()>0;
}
public function selectDatabase($db){
return $this->prepare($this->sqlSelectDatabase())->execute(array('db'=>$table));
}
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;
try{
parent::__construct($dsn, $username, $password, $options);
$this->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
} catch(PDOException $e){
throw new DatabaseException('Could not connect to the database server.', $e);
}
} else {
throw new DatabaseException("Database driver '$this->type' is not supported on this machine.'");
}
}
}
class MySQL extends Database{
function sqlTableExists(){
return "SHOW TABLES LIKE ':table'";
}
function sqlSelectDatabase(){
return "USE :db";
}
function __construct($username, $password, $dsn, $options = array()) {
parent::__construct($username, $password, $dsn, $options);
}
}
class PostgrSQL extends Database{
function sqlTableExists(){
return "select count(*) from pg_class where relname=':table' 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('usr', 'pw', array('host' => 'localhost', 'port' => 3306, 'dbname' => 'mydb'));
$db->exec('SET GLOBAL general_log_file = "/var/log/mysql.log";');
$db->exec("SET GLOBAL general_log = 'ON';");
echo $db->tableExists("settings") ? 'yes' : 'no'; // no, terwijl 100% de tabel bestaat.
} catch(PDOException $e){
echo $e->getMessage();
} catch(DatabaseException $e){
echo $e->getMessage();
}
?>
Iemand een idee? Geen foutmeldingen, niets. Volgens de code bestaat de tabel settings niet.