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:
2015-08-20 12:19:58 +00:00
parent 2238778dd6
commit e0b6aa77d2

View File

@@ -36,7 +36,7 @@ Optionnaly, you can add the
require_once ("domframework/verify.php");
/** Permit abstraction on the differents SQL databases available */
class dblayer extends PDO
class dblayer
{
/** The table name to use */
public $table = null;
@@ -84,7 +84,8 @@ class dblayer extends PDO
the table, and re-import the datas (http://www.sqlite.org/omitted.html) */
/** 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
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]))
throw new Exception (_("No valid DSN provided"), 500);
// Force specifics initialisations
$this->dsn = $dsn;
switch ($driver[0])
{
case "sqlite":
@@ -116,56 +118,76 @@ class dblayer extends PDO
file_exists ($file) &&
fileowner ($file) === posix_getuid ())
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);
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
if ($this->debug) echo "CONNECT TO DATABASE\n";
try
{
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
$driver_options);
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)
$this->exec("PRAGMA foreign_keys = ON");
self::$instance[$this->dsn]->exec ("PRAGMA foreign_keys = ON");
$this->sep = "`";
break;
case "mysql":
try
if (! array_key_exists ($this->dsn, self::$instance))
{
$driver_options[PDO::MYSQL_ATTR_FOUND_ROWS] = 1;
parent::__construct ($dsn, $username, $password, $driver_options);
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
if ($this->debug) echo "CONNECT TO DATABASE\n";
try
{
$driver_options[PDO::MYSQL_ATTR_FOUND_ROWS] = 1;
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
$driver_options);
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
$this->exec("SET CHARACTER SET utf8");
self::$instance[$this->dsn]->exec ("SET CHARACTER SET utf8");
$this->sep = "`";
break;
case "pgsql":
try
if (! array_key_exists ($this->dsn, self::$instance))
{
parent::__construct ($dsn, $username, $password, $driver_options);
parent::setAttribute (PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
throw new Exception ("PDO error : ".$e->getMessage(), 500);
if ($this->debug) echo "CONNECT TO DATABASE\n";
try
{
self::$instance[$this->dsn] = new PDO ($dsn, $username, $password,
$driver_options);
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
$this->exec("SET NAMES 'utf8'");
self::$instance[$this->dsn]->exec ("SET NAMES 'utf8'");
$this->sep = "\"";
break;
default:
throw new Exception (dgettext("domframework",
"Unknown PDO driver provided"), 500);
}
$this->dsn = $dsn;
return self::$instance[$this->dsn];
}
/** Return the connected database name from DSN used to connect */
@@ -192,11 +214,11 @@ class dblayer extends PDO
if ($this->sep === "")
throw new Exception (dgettext("domframework", "Database not connected"),
500);
switch ($this->getAttribute(PDO::ATTR_DRIVER_NAME))
switch (self::$instance[$this->dsn]->getAttribute(PDO::ATTR_DRIVER_NAME))
{
case "sqlite":
$req = "SELECT name FROM sqlite_master WHERE type='table'";
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
$st->execute ();
$res = array ();
while ($d = $st->fetch (PDO::FETCH_ASSOC))
@@ -206,7 +228,7 @@ class dblayer extends PDO
$req = "SELECT TABLE_NAME
FROM information_schema.tables
WHERE TABLE_SCHEMA='".$this->databasename()."'";
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
$st->execute ();
$res = array ();
while ($d = $st->fetch (PDO::FETCH_ASSOC))
@@ -216,7 +238,7 @@ class dblayer extends PDO
$req = "SELECT *
FROM pg_tables
WHERE schemaname = 'public'";
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
$st->execute ();
$res = array ();
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.
@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
@return an array with the errors in array($key=>array($priority,$message))
*/
@@ -275,7 +297,7 @@ class dblayer extends PDO
//." ". dgettext("domframework","in")." ".$key);
continue;
}
// Check for type inconsistencies if the value is provided
if (is_null ($datas[$key]))
{
@@ -286,7 +308,7 @@ class dblayer extends PDO
{
$errors[$key] = array ("error", sprintf (
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])));
continue;
}
@@ -400,12 +422,12 @@ class dblayer extends PDO
$this->unique = array ($this->primary);
// TODO : If Unique is not defined nor primary
// 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)
{
if ($this->primary === null)
{
return array (dgettext("domframework",
return array (dgettext("domframework",
"No field primary defined for tests in primary"));
}
@@ -491,7 +513,7 @@ class dblayer extends PDO
"FROM $this->sep$this->tableprefix$table$this->sep ".
"WHERE $this->sep$column$this->sep=:".md5 ($column);
if ($this->debug) echo "DEBUG : $req\n";
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
$val = $datas[$foreign];
$key = $column;
if ($this->debug) echo "DEBUG BIND : ".$this->fields[$foreign][0]."\n";
@@ -584,7 +606,7 @@ class dblayer extends PDO
$req .= " VALUES ";
$req .= "(:".implode (",:", $binds).")";
if ($this->debug) echo "DEBUG : $req\n";
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
foreach ($datasOK as $key=>$val)
{
if ($this->debug) echo "DEBUG BIND : $key(".md5 ($key).")->".
@@ -612,7 +634,7 @@ class dblayer extends PDO
echo "dblayer execute exception : ".$e->getMessage()."\n";
exit;
}
$lastID = $this->lastInsertId();
$lastID = self::$instance[$this->dsn]->lastInsertId();
$lastID = $this->hookpostinsert ($datasOK, $lastID);
return $lastID;
}
@@ -741,13 +763,13 @@ class dblayer extends PDO
if ($this->debug) echo "DEBUG : $req\n";
try
{
$st = $this->prepare ($req);
$st = self::$instance[$this->dsn]->prepare ($req);
}
catch (Exception $e)
{
if ($this->debug) echo "DEBUG : PREPARE ERROR ! Return FALSE".
$e->getMessage()."\n";
throw new Exception ($e->getMessage(), 500);
throw new Exception ($e->getMessage(), 500);
}
if ($select !== NULL)
@@ -784,7 +806,7 @@ class dblayer extends PDO
Return the number of rows modified
@param string|integer $updatekey The key applied on primary key to be
updated
@param array $datas The values to be updated
@param array $datas The values to be updated
@return the number of lines modified */
public function update ($updatekey, $datas)
{
@@ -826,7 +848,7 @@ class dblayer extends PDO
$req .= " WHERE $this->sep$this->primary$this->sep=:".
md5 ("PRIMARY".$this->primary);
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
// primary key
$fields = $this->fields;
@@ -886,7 +908,7 @@ class dblayer extends PDO
$deletekey = $this->hookpredelete ($deletekey);
$req = "DELETE FROM $this->sep$this->tableprefix$this->table$this->sep ";
$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 BIND : primary->".
var_export ($deletekey, TRUE)."\n";
@@ -926,7 +948,7 @@ class dblayer extends PDO
$sql = "DROP TABLE $this->sep$this->tableprefix$this->table$this->sep";
if ($this->debug)
echo "$sql\n";
return $this->exec($sql);
return self::$instance[$this->dsn]->exec ($sql);
}
/** Create the table defined by the differents fields.
@@ -953,7 +975,7 @@ class dblayer extends PDO
500);
if (count ($this->fields) === 0)
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":
$sql = "CREATE TABLE IF NOT EXISTS ".
@@ -1248,7 +1270,7 @@ class dblayer extends PDO
if ($this->debug)
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
@@ -1256,7 +1278,7 @@ class dblayer extends PDO
public function directRead ($sql)
{
if ($this->debug) echo "== Entering directRead\n";
$st = $this->prepare ($sql);
$st = self::$instance[$this->dsn]->prepare ($sql);
$st->execute ();
$res = array ();
while ($d = $st->fetch (PDO::FETCH_ASSOC))
@@ -1264,9 +1286,40 @@ class dblayer extends PDO
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
This hook is run before inserting a new data in the database, after the
verification
This hook is run before inserting a new data in the database, after the
verification
@param array the data to insert in the database
@return the modified datas */
public function hookpreinsert ($data)
@@ -1283,8 +1336,8 @@ class dblayer extends PDO
}
/** Hook preupdate
This hook is run before updating a data in the database, after the
verification
This hook is run before updating a data in the database, after the
verification
@return the modified datas */
public function hookpreupdate ($updatekey, $data)
{