Bonjour,
Cette classe permet d'étendre le module PDO.
La classe PdoManager ouvre la connexion en fonction de l'adapter passé.
Toutes les méthodes de PDO sont accessibles via la classe PdoManager grace a la fonction __call
Ex : appel de la méthode query
$oPdo = new DaoFactory::factory($aParams);
$oPdo->query('SELECT tata_yoyo FROM chapeau');
L'avantage est d'avoir des nom de méthode standardisé pour récupérer par exemple la liste des tables, la description des tables. Dans les classes PdoMysql et PdoPgsl on peut facilement ajouter des méthodes qui demandes des syntaxes SQL différentes selon les SGBD
Pour rajouter le support d'autre bdd il suffit par exemple de créer une class PdoMssql et d'y implémenter les méthodes obligatoires.
Voila c'est pas une classe très compliqué mais elle me sert beaucoup.
J'attend vaut critique et idées d'amélioration
Source / Exemple :
<?php
/**
- @abstract
- @name PdoManager
- @author aberthelot
- @since 11/10/2008
- @package Dao::Pdo
- @version 4.0.0 - AXB - 11/10/2008
- @version 4.0.1 - AXB - 14/11/2008 - Déportation de la méthode connect dans les classes filles
- /
abstract class PdoManager
{
/**
*
- @access protected
- @var string
- /
protected $_sHostname;
/**
*
- @access protected
- @var string
- /
protected $_sUsername;
/**
*
- @access protected
- @var string
- /
protected $_sPassword;
/**
- Adapter connexion
- Ex : mysql, pgsql
-
- @access protected
- @var string
- /
protected $_sAdapter;
/**
- Nom de la base de données
*
- @access protected
- @var string
- /
protected $_sBasename;
/**
*
- @access protected
- @var integer
- /
protected $_iPort;
/**
- Encodage de la base de données
*
- @access protected
- @var string
- /
protected $_sEncoding;
/**
- Connexion base de données
*
- @access protected
- @var object
- /
protected $_oPdoInstance = null;
/**
- Constructeur de la classe
- Initialise les variables de connexion
- Test si l'extension pdo est chargée
*
- @param array $aParams
- @return void
- /
public function __construct($aParams)
{
$this->_sAdapter = ( isset($aParams['adapter']) ) ? $aParams['adapter'] : null;
$this->_sHostname = ( isset($aParams['hostname']) ) ? $aParams['hostname'] : null;
$this->_sPassword = ( isset($aParams['password']) ) ? $aParams['password'] : null;
$this->_sUsername = ( isset($aParams['username']) ) ? $aParams['username'] : null;
$this->_sBasename = ( isset($aParams['basename']) ) ? $aParams['basename'] : null;
$this->_iPort = ( isset($aParams['port']) ) ? $aParams['port'] : null;
$this->_sEncoding = ( isset($aParams['encoding']) ) ? $aParams['encoding'] : null;
if( false === $this->checkExtensionPDo() )
{
throw new Exception('L\'extension "pdo" ou "pdo_'.$this->_sAdapter.'" ne sont pas activées.', E_ERROR);
}
}
/**
- Connexion à la base de données
- Passe la gestion des erreurs en exception
- Si mysql on active l'émulation des requêtes préparés
- Initialisation de l'encodage de la connexion
*
- @access public
- @return void
- /
public function connect()
{
if( is_null($this->_oPdoInstance) )
{
$this->_oPdoInstance = new PDO($this->_getDsn(), $this->_sUsername, $this->_sPassword);
$this->_oPdoInstance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if( $this->_oPdoInstance->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql' )
{
$this->_oPdoInstance->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
}
$this->_setConnectionEncoding();
}
}
/**
*
- @access public
- @param string $sMethod
- @param array $aArguments
- @return mixed|boolean
- /
public function __call($sMethod, $aArguments)
{
if( method_exists(get_class($this->_oPdoInstance), $sMethod) )
{
return call_user_func_array(array($this->_oPdoInstance, $sMethod), $aArguments);
}
return false;
}
/**
- Retourne la liste des drivers disponible
*
- @static
- @access public
- @return array
- /
public static function getAvailableDrivers()
{
return PDO::getAvailableDrivers();
}
/**
- Ferme la connexion à la base de données
*
- @access public
- @return void
- /
public function close()
{
$this->_oPdoInstance = null;
}
/**
- Test si l'extension pdo est activé
*
- @access private
- @return boolean
- /
private function checkExtensionPDo()
{
if ( extension_loaded('pdo') )
{
if( extension_loaded('pdo_'.$this->_sAdapter) )
{
return true;
}
}
return false;
}
/**
- Retourne le driver de connexion
*
- @abstract
- @access protected
- @return void
- /
abstract protected function _getDsn();
/**
- Modifie l'encodage de la connexion
*
- @abstract
- @access protected
- @return void
- /
abstract protected function _setConnectionEncoding();
/**
- Retourne la description de la table
*
- @abstract
- @access public
- @param string $sNameTable
- @param string $sSchema
- @return array
- /
abstract public function describe($sNameTable, $sSchema = null);
/**
- Retourne la liste des tables de la base
*
- @abstract
- @access public
- @return array
- /
abstract public function listTable();
}
?>
<?php
/**
- @name PdoMysql
- @author aberthelot
- @since 11/10/2008
- @package Dao::Pdo
- @version 4.0.0 - AXB - 11/10/2008
- /
class PdoMysql extends PdoManager
{
/**
- Constructeur de la classe
- Initialise les variables de connexion
- Test si l'extension pdo est chargée
*
- @param array $aParams
- @return void
- /
public function __construct($aParams)
{
parent::__construct($aParams);
}
/**
- Retourne la description de la table
*
- @access public
- @param string $sNameTable
- @param string $sSchema
- @return array
- /
public function describe($sNameTable, $sSchema = null)
{
$aData = array();
$sSql = 'SHOW COLUMNS FROM '.$sNameTable.';';
$aRes = $this->query($sSql);
$aRows = $aRes->fetchAll();
foreach($aRows as $iKey => $sValue)
{
$aData[$sValue['Field']]['name'] = $sValue['Field'];
$aData[$sValue['Field']]['type'] = $sValue['Type'];
$aData[$sValue['Field']]['null'] = ($sValue['Null'] == 'YES') ? true : false;
$aData[$sValue['Field']]['key'] = ($sValue['Key'] == 'PRI') ? true : false;
$aData[$sValue['Field']]['default'] = $sValue['Default'];
$aData[$sValue['Field']]['extra'] = $sValue['Extra'];
}
return $aData;
}
/**
- Retourne la liste des tables de la base
*
- @access public
- @return array
- /
public function listTable()
{
$aData = array();
$sSql = 'SHOW TABLES;';
$aRes = $this->query($sSql);
$aRows = $aRes->fetchAll();
foreach($aRows as $iKey => $sValue)
{
$aData[$iKey] = $sValue['Tables_in_'.$this->_sBasename];
}
return $aData;
}
/**
- Retourne le driver de connexion
*
- @abstract
- @access protected
- @return void
- /
protected function _getDsn()
{
return 'mysql:host='.$this->_sHostname.';dbname='.$this->_sBasename;
}
/**
- Modifie l'encodage de la connexion
*
- @access protected
- @return void
- /
protected function _setConnectionEncoding()
{
if(! is_null($this->_sEncoding) )
{
$sStmt = $this->_oPdoInstance->prepare('SET CHARACTER SET ?');
$this->execute(array($this->_sEncoding));
}
}
}
?>
<?php
/**
- @name PdoPgsql
- @author aberthelot
- @since 11/10/2008
- @package Dao::Pdo
- @version 4.0.0 - AXB - 11/10/2008
- /
class PdoPgsql extends PdoManager
{
/**
- Constructeur de la classe
- Initialise les variables de connexion
- Test si l'extension pdo est chargée
*
- @param array $aParams
- @return void
- /
public function __construct($aParams)
{
parent::__construct($aParams);
}
/**
- Retourne la description de la table
*
- @access public
- @param string $sNameTable
- @param string $sSchema
- @return array
- /
public function describe($sNameTable, $sSchema = null)
{
$aData = array();
$sSql = "SELECT a.attnum, n.nspname, c.relname, a.attname AS colname, t.typname AS type, a.atttypmod, ";
$sSql .= "FORMAT_TYPE(a.atttypid, a.atttypmod) AS complete_type, d.adsrc AS default_value, ";
$sSql .= "a.attnotnull AS notnull, a.attlen AS length, co.contype, ARRAY_TO_STRING(co.conkey, ',') AS conkey ";
$sSql .= "FROM pg_attribute AS a ";
$sSql .= "JOIN pg_class AS c ON a.attrelid = c.oid ";
$sSql .= "JOIN pg_namespace AS n ON c.relnamespace = n.oid ";
$sSql .= "JOIN pg_type AS t ON a.atttypid = t.oid ";
$sSql .= "LEFT OUTER JOIN pg_constraint AS co ON (co.conrelid = c.oid ";
$sSql .= "AND a.attnum = ANY(co.conkey) AND co.contype = 'p') ";
$sSql .= "LEFT OUTER JOIN pg_attrdef AS d ON d.adrelid = c.oid AND d.adnum = a.attnum ";
$sSql .= "WHERE a.attnum > 0 AND c.relname = '".$sNameTable."' ";
$sSql .= ( is_null($sSchema) ) ? '' : " AND n.nspname = '".$sSchema."' ";
$sSql .= "ORDER BY a.attnum;";
$aRes = $this->query($sSql);
$aRows = $aRes->fetchAll();
foreach($aRows as $iKey => $sValue)
{
$aData[$sValue['colname']]['name'] = $sValue['colname'];
$aData[$sValue['colname']]['type'] = $sValue['complete_type'];
$aData[$sValue['colname']]['null'] = ($sValue['notnull'] == 1) ? true : false;
$aData[$sValue['colname']]['key'] = ($sValue['contype'] == 'P') ? true : false;
$aData[$sValue['colname']]['default'] = $sValue['default_value'];
}
return $aData;
}
/**
- Retourne la liste des tables de la base
*
- @access public
- @return array
- /
public function listTable()
{
$aData = array();
$sSql = "SELECT c.relname AS table_name ";
$sSql .= "FROM pg_class c, pg_user u ";
$sSql .= "WHERE c.relowner = u.usesysid AND c.relkind = 'r' ";
$sSql .= "AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) ";
$sSql .= "AND c.relname !~ '^(pg_|sql_)' ";
$sSql .= "UNION ";
$sSql .= "SELECT c.relname AS table_name ";
$sSql .= "FROM pg_class c ";
$sSql .= "WHERE c.relkind = 'r' ";
$sSql .= "AND NOT EXISTS (SELECT 1 FROM pg_views WHERE viewname = c.relname) ";
$sSql .= "AND NOT EXISTS (SELECT 1 FROM pg_user WHERE usesysid = c.relowner) ";
$sSql .= "AND c.relname !~ '^pg_';";
$aRes = $this->query($sSql);
$aRows = $aRes->fetchAll();
foreach($aRows as $iKey => $sValue)
{
$aData[$iKey] = $sValue['table_name'];
}
return $aData;
}
/**
- Retourne le driver de connexion
*
- @abstract
- @access protected
- @return void
- /
protected function _getDsn()
{
return 'pgsql:host='.$this->_sHostname.';dbname='.$this->_sBasename;
}
/**
- Modifie l'encodage de la connexion
*
- @access protected
- @return void
- /
protected function _setConnectionEncoding()
{
if(! is_null($this->_sEncoding) )
{
$stmt = $this->_oPdoInstance->prepare('SET client_encoding TO ?');
$this->execute(array($this->_sEncoding));
}
}
}
?>
<?php
namespace Dao;
/**
- @name DaoFactory
- @author aberthelot
- @since 11/10/2008
- @package Dao
- @version 4.0.0 - AXB - 11/10/2008
- /
class DaoFactory
{
/**
- Factory
- Retourne une instance de la classe désigné par $sType
*
- @param array $aParams
- @return object
- /
public static function factory(array $aParams)
{
if( isset($aParams['adapter']) )
{
$sClass = 'Pdo'.ucfirst(strtolower($aParams['adapter']));
$oReflection = new ReflectionClass($sClass);
if(! $oReflection->isSubclassOf('PdoManager') )
{
throw new InvalidArgumentException($sClass.' n\'est pas une classe enfant de "PdoManager".', E_ERROR);
}
$oInstance = new $sClass($aParams);
return $oInstance;
}
else
{
throw new Exception('Aucun type de base de données spécifié.', E_ERROR);
}
}
}
?>
##### EXEMPLES #####
<?php
$oPdo = new DaoFactory::factory($aParams);
$sStmt = $oPdo->query('SELECT tata_yoyo FROM chapeau');
$aRes = $sStmt->fetchAll();
print '<pre>';
print_r($aRes);
print '</pre>';
?>
4 janv. 2009 à 12:54
4 janv. 2009 à 13:45
Tu devrais préciser que la version de PHP requise est 5.3, parce que sinon, y'en a pas mal qui vont pas comprendre les messages d'erreurs alors qu'ils sont avec la dernière version stable ;)
C'est la première source que je vois qui nécessite PHP5.3 : ça fait plaisir, mais ça pourrait être intéressant de faire fonctionner ça sur PHP 5.2.x
J'ai pas regardé le code en détail (comme toujours... désolé... :/ ) mais avoir un commentaire comme ça de la part de WebDeb, c'est une belle performance. Donc rien que pour ça, chapeau !
@WebDeb : euh je ne te critique pas, hein, c'est juste que comme tu es exigeant (et c'est une qualité pour moi), il est rare que tu laisses un commentaire qui laisse penser que la source est parfaite... D'où la performance...
Et bonne année tout ça tout ça *=/:-)
4 janv. 2009 à 14:06
4 janv. 2009 à 15:57
Merci pour vos commentaire ça fait plaisir.
Je suis en train de faire une petite mise a jour pour pouvooir lancer une action sur certaine méthode de pdo
Par exemple logger des requetes.
Je met la source a jour des que c'est fini
29 janv. 2009 à 21:35
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.