dblayer : add a Singleton to not reconnect each time we need to access the same database.
dblayer : add a method to disconnect the database engine dblayer : add the transactions methods, linke in PDO dblayer : remove the extension of PDO git-svn-id: https://svn.fournier38.fr/svn/ProgSVN/trunk@2259 bf3deb0d-5f1a-0410-827f-c0cc1f45334c
This commit is contained in:
159
dblayer.php
159
dblayer.php
@@ -36,7 +36,7 @@ Optionnaly, you can add the
|
|||||||
require_once ("domframework/verify.php");
|
require_once ("domframework/verify.php");
|
||||||
|
|
||||||
/** Permit abstraction on the differents SQL databases available */
|
/** Permit abstraction on the differents SQL databases available */
|
||||||
class dblayer extends PDO
|
class dblayer
|
||||||
{
|
{
|
||||||
/** The table name to use */
|
/** The table name to use */
|
||||||
public $table = null;
|
public $table = null;
|
||||||
@@ -84,7 +84,8 @@ class dblayer extends PDO
|
|||||||
the table, and re-import the datas (http://www.sqlite.org/omitted.html) */
|
the table, and re-import the datas (http://www.sqlite.org/omitted.html) */
|
||||||
|
|
||||||
/** Limit to one instance of the connection to the same database */
|
/** Limit to one instance of the connection to the same database */
|
||||||
private static $instance = null;
|
// Based on an idea of http://tonylandis.com/php/php5-pdo-singleton-class/
|
||||||
|
private static $instance = array ();
|
||||||
|
|
||||||
/** Connection to the database engine
|
/** Connection to the database engine
|
||||||
See http://fr2.php.net/manual/en/pdo.construct.php for the $dsn format
|
See http://fr2.php.net/manual/en/pdo.construct.php for the $dsn format
|
||||||
@@ -99,6 +100,7 @@ class dblayer extends PDO
|
|||||||
if (! isset ($driver[0]))
|
if (! isset ($driver[0]))
|
||||||
throw new Exception (_("No valid DSN provided"), 500);
|
throw new Exception (_("No valid DSN provided"), 500);
|
||||||
// Force specifics initialisations
|
// Force specifics initialisations
|
||||||
|
$this->dsn = $dsn;
|
||||||
switch ($driver[0])
|
switch ($driver[0])
|
||||||
{
|
{
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
@@ -116,56 +118,76 @@ class dblayer extends PDO
|
|||||||
file_exists ($file) &&
|
file_exists ($file) &&
|
||||||
fileowner ($file) === posix_getuid ())
|
fileowner ($file) === posix_getuid ())
|
||||||
chmod ($file, 0666);
|
chmod ($file, 0666);
|
||||||
try
|
// Print the instances of PDO objects stored :
|
||||||
|
// var_dump (self::$instance);
|
||||||
|
if (! array_key_exists ($this->dsn, self::$instance))
|
||||||
{
|
{
|
||||||
parent::__construct ($dsn, $username, $password, $driver_options);
|
if ($this->debug) echo "CONNECT TO DATABASE\n";
|
||||||
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception $e)
|
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
|
||||||
{
|
$driver_options);
|
||||||
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
self::$instance[$this->dsn]->setAttribute (PDO::ATTR_ERRMODE,
|
||||||
|
PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force ForeignKeys support (disabled by default)
|
// Force ForeignKeys support (disabled by default)
|
||||||
$this->exec("PRAGMA foreign_keys = ON");
|
self::$instance[$this->dsn]->exec ("PRAGMA foreign_keys = ON");
|
||||||
$this->sep = "`";
|
$this->sep = "`";
|
||||||
break;
|
break;
|
||||||
case "mysql":
|
case "mysql":
|
||||||
try
|
if (! array_key_exists ($this->dsn, self::$instance))
|
||||||
{
|
{
|
||||||
$driver_options[PDO::MYSQL_ATTR_FOUND_ROWS] = 1;
|
if ($this->debug) echo "CONNECT TO DATABASE\n";
|
||||||
parent::__construct ($dsn, $username, $password, $driver_options);
|
try
|
||||||
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
{
|
||||||
}
|
$driver_options[PDO::MYSQL_ATTR_FOUND_ROWS] = 1;
|
||||||
catch (Exception $e)
|
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
|
||||||
{
|
$driver_options);
|
||||||
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
self::$instance[$this->dsn]->setAttribute (PDO::ATTR_ERRMODE,
|
||||||
|
PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the coding to UTF8
|
// Set the coding to UTF8
|
||||||
$this->exec("SET CHARACTER SET utf8");
|
self::$instance[$this->dsn]->exec ("SET CHARACTER SET utf8");
|
||||||
$this->sep = "`";
|
$this->sep = "`";
|
||||||
break;
|
break;
|
||||||
case "pgsql":
|
case "pgsql":
|
||||||
try
|
if (! array_key_exists ($this->dsn, self::$instance))
|
||||||
{
|
{
|
||||||
parent::__construct ($dsn, $username, $password, $driver_options);
|
if ($this->debug) echo "CONNECT TO DATABASE\n";
|
||||||
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception $e)
|
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
|
||||||
{
|
$driver_options);
|
||||||
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
self::$instance[$this->dsn]->setAttribute (PDO::ATTR_ERRMODE,
|
||||||
|
PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
catch (Exception $e)
|
||||||
|
{
|
||||||
|
throw new Exception ("PDO error : ".$e->getMessage(), 500);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the coding to UTF8
|
// Set the coding to UTF8
|
||||||
$this->exec("SET NAMES 'utf8'");
|
self::$instance[$this->dsn]->exec ("SET NAMES 'utf8'");
|
||||||
$this->sep = "\"";
|
$this->sep = "\"";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Exception (dgettext("domframework",
|
throw new Exception (dgettext("domframework",
|
||||||
"Unknown PDO driver provided"), 500);
|
"Unknown PDO driver provided"), 500);
|
||||||
}
|
}
|
||||||
$this->dsn = $dsn;
|
return self::$instance[$this->dsn];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return the connected database name from DSN used to connect */
|
/** Return the connected database name from DSN used to connect */
|
||||||
@@ -192,11 +214,11 @@ class dblayer extends PDO
|
|||||||
if ($this->sep === "")
|
if ($this->sep === "")
|
||||||
throw new Exception (dgettext("domframework", "Database not connected"),
|
throw new Exception (dgettext("domframework", "Database not connected"),
|
||||||
500);
|
500);
|
||||||
switch ($this->getAttribute(PDO::ATTR_DRIVER_NAME))
|
switch (self::$instance[$this->dsn]->getAttribute(PDO::ATTR_DRIVER_NAME))
|
||||||
{
|
{
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
$req = "SELECT name FROM sqlite_master WHERE type='table'";
|
$req = "SELECT name FROM sqlite_master WHERE type='table'";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
$st->execute ();
|
$st->execute ();
|
||||||
$res = array ();
|
$res = array ();
|
||||||
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
||||||
@@ -206,7 +228,7 @@ class dblayer extends PDO
|
|||||||
$req = "SELECT TABLE_NAME
|
$req = "SELECT TABLE_NAME
|
||||||
FROM information_schema.tables
|
FROM information_schema.tables
|
||||||
WHERE TABLE_SCHEMA='".$this->databasename()."'";
|
WHERE TABLE_SCHEMA='".$this->databasename()."'";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
$st->execute ();
|
$st->execute ();
|
||||||
$res = array ();
|
$res = array ();
|
||||||
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
||||||
@@ -216,7 +238,7 @@ class dblayer extends PDO
|
|||||||
$req = "SELECT *
|
$req = "SELECT *
|
||||||
FROM pg_tables
|
FROM pg_tables
|
||||||
WHERE schemaname = 'public'";
|
WHERE schemaname = 'public'";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
$st->execute ();
|
$st->execute ();
|
||||||
$res = array ();
|
$res = array ();
|
||||||
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
||||||
@@ -230,7 +252,7 @@ class dblayer extends PDO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Verify if the provided datas can be inserted/updated in the database.
|
/** Verify if the provided datas can be inserted/updated in the database.
|
||||||
@param $datas An array containing the datas to verify with keys
|
@param $datas An array containing the datas to verify with keys
|
||||||
@param $updatekey the key to update
|
@param $updatekey the key to update
|
||||||
@return an array with the errors in array($key=>array($priority,$message))
|
@return an array with the errors in array($key=>array($priority,$message))
|
||||||
*/
|
*/
|
||||||
@@ -275,7 +297,7 @@ class dblayer extends PDO
|
|||||||
//." ". dgettext("domframework","in")." ".$key);
|
//." ". dgettext("domframework","in")." ".$key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for type inconsistencies if the value is provided
|
// Check for type inconsistencies if the value is provided
|
||||||
if (is_null ($datas[$key]))
|
if (is_null ($datas[$key]))
|
||||||
{
|
{
|
||||||
@@ -286,7 +308,7 @@ class dblayer extends PDO
|
|||||||
{
|
{
|
||||||
$errors[$key] = array ("error", sprintf (
|
$errors[$key] = array ("error", sprintf (
|
||||||
dgettext("domframework",
|
dgettext("domframework",
|
||||||
"Errors in consistency : '%s' is not an integer or a string [is %s]"),
|
"Errors in consistency : '%s' is not an integer or a string [is %s]"),
|
||||||
$key, gettype ($datas[$key])));
|
$key, gettype ($datas[$key])));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -400,12 +422,12 @@ class dblayer extends PDO
|
|||||||
$this->unique = array ($this->primary);
|
$this->unique = array ($this->primary);
|
||||||
// TODO : If Unique is not defined nor primary
|
// TODO : If Unique is not defined nor primary
|
||||||
// FIXME : If unique is defined, could I test if the primary key is defined
|
// FIXME : If unique is defined, could I test if the primary key is defined
|
||||||
// in a parameter of the unique and if it is not add it automatically
|
// in a parameter of the unique and if it is not add it automatically
|
||||||
foreach ($this->unique as $k=>$columns)
|
foreach ($this->unique as $k=>$columns)
|
||||||
{
|
{
|
||||||
if ($this->primary === null)
|
if ($this->primary === null)
|
||||||
{
|
{
|
||||||
return array (dgettext("domframework",
|
return array (dgettext("domframework",
|
||||||
"No field primary defined for tests in primary"));
|
"No field primary defined for tests in primary"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,7 +513,7 @@ class dblayer extends PDO
|
|||||||
"FROM $this->sep$this->tableprefix$table$this->sep ".
|
"FROM $this->sep$this->tableprefix$table$this->sep ".
|
||||||
"WHERE $this->sep$column$this->sep=:".md5 ($column);
|
"WHERE $this->sep$column$this->sep=:".md5 ($column);
|
||||||
if ($this->debug) echo "DEBUG : $req\n";
|
if ($this->debug) echo "DEBUG : $req\n";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
$val = $datas[$foreign];
|
$val = $datas[$foreign];
|
||||||
$key = $column;
|
$key = $column;
|
||||||
if ($this->debug) echo "DEBUG BIND : ".$this->fields[$foreign][0]."\n";
|
if ($this->debug) echo "DEBUG BIND : ".$this->fields[$foreign][0]."\n";
|
||||||
@@ -584,7 +606,7 @@ class dblayer extends PDO
|
|||||||
$req .= " VALUES ";
|
$req .= " VALUES ";
|
||||||
$req .= "(:".implode (",:", $binds).")";
|
$req .= "(:".implode (",:", $binds).")";
|
||||||
if ($this->debug) echo "DEBUG : $req\n";
|
if ($this->debug) echo "DEBUG : $req\n";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
foreach ($datasOK as $key=>$val)
|
foreach ($datasOK as $key=>$val)
|
||||||
{
|
{
|
||||||
if ($this->debug) echo "DEBUG BIND : $key(".md5 ($key).")->".
|
if ($this->debug) echo "DEBUG BIND : $key(".md5 ($key).")->".
|
||||||
@@ -612,7 +634,7 @@ class dblayer extends PDO
|
|||||||
echo "dblayer execute exception : ".$e->getMessage()."\n";
|
echo "dblayer execute exception : ".$e->getMessage()."\n";
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
$lastID = $this->lastInsertId();
|
$lastID = self::$instance[$this->dsn]->lastInsertId();
|
||||||
$lastID = $this->hookpostinsert ($datasOK, $lastID);
|
$lastID = $this->hookpostinsert ($datasOK, $lastID);
|
||||||
return $lastID;
|
return $lastID;
|
||||||
}
|
}
|
||||||
@@ -741,13 +763,13 @@ class dblayer extends PDO
|
|||||||
if ($this->debug) echo "DEBUG : $req\n";
|
if ($this->debug) echo "DEBUG : $req\n";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
}
|
}
|
||||||
catch (Exception $e)
|
catch (Exception $e)
|
||||||
{
|
{
|
||||||
if ($this->debug) echo "DEBUG : PREPARE ERROR ! Return FALSE".
|
if ($this->debug) echo "DEBUG : PREPARE ERROR ! Return FALSE".
|
||||||
$e->getMessage()."\n";
|
$e->getMessage()."\n";
|
||||||
throw new Exception ($e->getMessage(), 500);
|
throw new Exception ($e->getMessage(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($select !== NULL)
|
if ($select !== NULL)
|
||||||
@@ -784,7 +806,7 @@ class dblayer extends PDO
|
|||||||
Return the number of rows modified
|
Return the number of rows modified
|
||||||
@param string|integer $updatekey The key applied on primary key to be
|
@param string|integer $updatekey The key applied on primary key to be
|
||||||
updated
|
updated
|
||||||
@param array $datas The values to be updated
|
@param array $datas The values to be updated
|
||||||
@return the number of lines modified */
|
@return the number of lines modified */
|
||||||
public function update ($updatekey, $datas)
|
public function update ($updatekey, $datas)
|
||||||
{
|
{
|
||||||
@@ -826,7 +848,7 @@ class dblayer extends PDO
|
|||||||
$req .= " WHERE $this->sep$this->primary$this->sep=:".
|
$req .= " WHERE $this->sep$this->primary$this->sep=:".
|
||||||
md5 ("PRIMARY".$this->primary);
|
md5 ("PRIMARY".$this->primary);
|
||||||
if ($this->debug) echo "DEBUG : $req\n";
|
if ($this->debug) echo "DEBUG : $req\n";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
// Add the primary key to field list temporaly. It will permit to update the
|
// Add the primary key to field list temporaly. It will permit to update the
|
||||||
// primary key
|
// primary key
|
||||||
$fields = $this->fields;
|
$fields = $this->fields;
|
||||||
@@ -886,7 +908,7 @@ class dblayer extends PDO
|
|||||||
$deletekey = $this->hookpredelete ($deletekey);
|
$deletekey = $this->hookpredelete ($deletekey);
|
||||||
$req = "DELETE FROM $this->sep$this->tableprefix$this->table$this->sep ";
|
$req = "DELETE FROM $this->sep$this->tableprefix$this->table$this->sep ";
|
||||||
$req .= "WHERE $this->primary = :primary";
|
$req .= "WHERE $this->primary = :primary";
|
||||||
$st = $this->prepare ($req);
|
$st = self::$instance[$this->dsn]->prepare ($req);
|
||||||
if ($this->debug) echo "DEBUG : $req\n";
|
if ($this->debug) echo "DEBUG : $req\n";
|
||||||
if ($this->debug) echo "DEBUG BIND : primary->".
|
if ($this->debug) echo "DEBUG BIND : primary->".
|
||||||
var_export ($deletekey, TRUE)."\n";
|
var_export ($deletekey, TRUE)."\n";
|
||||||
@@ -926,7 +948,7 @@ class dblayer extends PDO
|
|||||||
$sql = "DROP TABLE $this->sep$this->tableprefix$this->table$this->sep";
|
$sql = "DROP TABLE $this->sep$this->tableprefix$this->table$this->sep";
|
||||||
if ($this->debug)
|
if ($this->debug)
|
||||||
echo "$sql\n";
|
echo "$sql\n";
|
||||||
return $this->exec($sql);
|
return self::$instance[$this->dsn]->exec ($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create the table defined by the differents fields.
|
/** Create the table defined by the differents fields.
|
||||||
@@ -953,7 +975,7 @@ class dblayer extends PDO
|
|||||||
500);
|
500);
|
||||||
if (count ($this->fields) === 0)
|
if (count ($this->fields) === 0)
|
||||||
throw new Exception (dgettext("domframework", "No Field defined"), 500);
|
throw new Exception (dgettext("domframework", "No Field defined"), 500);
|
||||||
switch ($this->getAttribute(PDO::ATTR_DRIVER_NAME))
|
switch (self::$instance[$this->dsn]->getAttribute(PDO::ATTR_DRIVER_NAME))
|
||||||
{
|
{
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
$sql = "CREATE TABLE IF NOT EXISTS ".
|
$sql = "CREATE TABLE IF NOT EXISTS ".
|
||||||
@@ -1248,7 +1270,7 @@ class dblayer extends PDO
|
|||||||
|
|
||||||
if ($this->debug)
|
if ($this->debug)
|
||||||
echo "$sql\n";
|
echo "$sql\n";
|
||||||
return $this->exec($sql);
|
return self::$instance[$this->dsn]->exec ($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** This function permit to send a SQL request to the database to do a SELECT
|
/** This function permit to send a SQL request to the database to do a SELECT
|
||||||
@@ -1256,7 +1278,7 @@ class dblayer extends PDO
|
|||||||
public function directRead ($sql)
|
public function directRead ($sql)
|
||||||
{
|
{
|
||||||
if ($this->debug) echo "== Entering directRead\n";
|
if ($this->debug) echo "== Entering directRead\n";
|
||||||
$st = $this->prepare ($sql);
|
$st = self::$instance[$this->dsn]->prepare ($sql);
|
||||||
$st->execute ();
|
$st->execute ();
|
||||||
$res = array ();
|
$res = array ();
|
||||||
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
while ($d = $st->fetch (PDO::FETCH_ASSOC))
|
||||||
@@ -1264,9 +1286,40 @@ class dblayer extends PDO
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** This function disconnect the database. It is normally only used in phpunit
|
||||||
|
unit tests */
|
||||||
|
public function disconnect ()
|
||||||
|
{
|
||||||
|
unset (self::$instance[$this->dsn]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The prepare method */
|
||||||
|
public function prepare ($statement, $driver_options = array())
|
||||||
|
{
|
||||||
|
return self::$instance[$this->dsn]->prepare ($statement, $driver_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Start a new Transaction */
|
||||||
|
public function beginTransaction ()
|
||||||
|
{
|
||||||
|
return self::$instance[$this->dsn]->beginTransaction ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Commit (validate) a transaction */
|
||||||
|
public function commit ()
|
||||||
|
{
|
||||||
|
return self::$instance[$this->dsn]->commit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** RollBack a transaction */
|
||||||
|
public function rollback ()
|
||||||
|
{
|
||||||
|
return self::$instance[$this->dsn]->rollback ();
|
||||||
|
}
|
||||||
|
|
||||||
/** Hook preinsert
|
/** Hook preinsert
|
||||||
This hook is run before inserting a new data in the database, after the
|
This hook is run before inserting a new data in the database, after the
|
||||||
verification
|
verification
|
||||||
@param array the data to insert in the database
|
@param array the data to insert in the database
|
||||||
@return the modified datas */
|
@return the modified datas */
|
||||||
public function hookpreinsert ($data)
|
public function hookpreinsert ($data)
|
||||||
@@ -1283,8 +1336,8 @@ class dblayer extends PDO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Hook preupdate
|
/** Hook preupdate
|
||||||
This hook is run before updating a data in the database, after the
|
This hook is run before updating a data in the database, after the
|
||||||
verification
|
verification
|
||||||
@return the modified datas */
|
@return the modified datas */
|
||||||
public function hookpreupdate ($updatekey, $data)
|
public function hookpreupdate ($updatekey, $data)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user