begin process at 2012 05 27 22:15:58
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Base de données

 > CLASSE MYSQL UTILISANT LES FONCTIONS PDO

CLASSE MYSQL UTILISANT LES FONCTIONS PDO


 Information sur la source

 Description

Ceci est une classe que j'ai développé pour mes besoin personnels.
Elle permet de se connecter à une base MySQL et utilise l'extension PHP Data Objets (PDO). Exit les traditionnelles fonctions mysql_.
PHP5 est donc requis ainsi que l'activation de la prise en charge de MySQL dans PDO.

Les fonctions présentes sont soit des fonctions que j'utilise régulièrement, soit des fonctions dont j'ai eu l'utilité à un moment donné.

Je vous le partage en espérant qu'elle puisse être utile à certains et, comme rien n'est parfait, je reste ouvert à toute critique constructive. :)

Source

  • <?php
  • /**
  • * Classe de manipulation de base MySQL
  • *
  • * Dernière mise à jour : 17/09/2010
  • **/
  • class Db
  • {
  • private $connection = false; //Instance PDO
  • private $ActiveTransaction = false; //Flag indiquant si une transaction a été démarrée
  • private $sql = ''; //Dernière requête SQL executée
  • /** Fonction Constructeur
  • * Desc : Initialise la connexion
  • * Params : (string)$Serveur = Adresse du serveur MySQL
  • * (string)$Utilisateur = Nom d'utilisateur de la base MySQL
  • * (string)$MotDePasse = Mot de passe MySQL
  • * (string)$BaseDeDonnees = Nom de la base de données
  • * Return : Void
  • **/
  • public function __construct($Serveur, $Utilisateur, $MotDePasse, $BaseDeDonnees)
  • {
  • try {
  • //On instancie l'objet PDO et on se connecte à la base
  • $this->connection = new PDO('mysql:host='.$Serveur.';dbname='.$BaseDeDonnees, $Utilisateur, $MotDePasse, array(PDO::ATTR_PERSISTENT => true));
  • } catch (PDOException $e) {
  • //En cas d'erreur, on affiche un message avec l'erreur retournée
  • echo 'Connexion &eacute;chou&eacute;e : <b>'.$e->getMessage().'</b>';
  • }
  • }
  • /** Fonction BeginTransaction
  • * Desc : Démarre une transaction MySQL
  • * Params : None
  • * Return : Void
  • **/
  • public function BeginTransaction()
  • {
  • //S'il n'existe pas de transaction active, on l'active
  • if (!$this->ActiveTransaction)
  • $this->ActiveTransaction = $this->connection->beginTransaction();
  • }
  • /** Fonction CommitTransaction
  • * Desc : Valide une transaction MySQL
  • * Params : None
  • * Return : (bool)true si la validation s'est bien passée, sinon false
  • **/
  • public function CommitTransaction()
  • {
  • try {
  • //Si une transaction est active
  • if ($this->ActiveTransaction)
  • {
  • //On la valide
  • if ($this->connection->commit())
  • {
  • //Il n'y a plus de transaction active
  • $this->ActiveTransaction = false;
  • //La validation s'est bien passée donc on retourne true
  • return true;
  • }
  • else
  • {
  • //Si la validation retourne false, on créé une erreur
  • Throw new Exception('La transaction n\'a pas pu &ecirc;tre valid&eacute;e.<br />'.$this->GetError());
  • }
  • } else {
  • //S'il n'y a pas de transaction active, on créé une erreur
  • Throw new Exception('Aucune transaction active');
  • }
  • } catch (Exception $e) {
  • //En cas d'erreur, on affiche un message avec l'erreur retournée
  • echo 'Impossible de valider la transaction : <b>'.$e->getMessage().'</b>';
  • return false;
  • }
  • }
  • /** Fonction GetFrom
  • * Desc : Retourne un tableau contenant les enregistrements selon les conditions spécifiées
  • * Params : (string|array)$Table = Table SQL
  • * (string|array)$Fields = Champ(s) à retourner
  • * (string|array)$Where = Conditions WHERE
  • * (string|array)$Order = Champ(s) de tri
  • * (string|array)$GroupBy = Champ(s) à grouper
  • * (string)$Limit = Limitation de la requête
  • * Return : (array)résultat de la requête
  • **/
  • public function GetFrom($Table, $Fields = false, $Order = false, $Where = false, $GroupBy = false, $Limit = false)
  • {
  • //On initialise une nouvelle requête
  • $Sql = '';
  • //On créé la requête section par section
  • //Section SELECT
  • $Sql .= $this->MakeSQLPart('SELECT', $Fields?$Fields:'*');
  • //Section FROM
  • $Sql .= $this->MakeSQLPart('FROM', $Table);
  • //Section WHERE
  • $Sql .= $this->MakeSQLPart('WHERE', $Where);
  • //Section ORDER BY
  • $Sql .= $this->MakeSQLPart('ORDER BY', $Order);
  • //Group By s'il y a
  • $Sql .= $this->MakeSQLPart('GROUP BY', $GroupBy);
  • //Limit s'il y a
  • $Sql .= $this->MakeSQLPart('LIMIT', $Limit);
  • //On retourne le tableau de résultat renvoyé par la fonction Query2Array();
  • return $this->Query2Array($Sql);
  • }
  • /** Fonction GetValue
  • * Desc : Retourne une valeur recherchée dans la base
  • * Params : (string)$Table = Table SQL
  • * (string|array)$Field = Champ recherché
  • * (string|array)$Where = Critère WHERE
  • * Return : (string)valeur trouvée, sinon false
  • **/
  • public function GetValue($Table, $Field, $Where)
  • {
  • //On requête pour obtenir la valeur recherchée
  • $result = $this->GetFrom($Table, 'DISTINCT('.$Field.')', false, $Where);
  • //Si la requête a renvoyé un résultat
  • if (count($result) === 1) {
  • //On vérifie si la variable $Field a été renseigné avec la table
  • //Du type matable.monchamp
  • //On récupère la position du point
  • $PositionPoint = strpos($Field, '.');
  • //Et on déduit le nom du champ
  • $FieldName = substr($Field, $PositionPoint ? $PositionPoint + 1 : 0);
  • //On retourne la valeur recherchée
  • return $result[0][$FieldName];
  • } else {
  • //Sinon il n'y a aucun ou plus d'un résultat donc on retourne false
  • //Car on veut retourner une et une seule valeur
  • return false;
  • }
  • }
  • /** Fonction InTable
  • * Desc : Indique si une valeur est contenue par la table et le champ donné
  • * Params : (string)$Needle = valeur recherchée
  • * (string)$Table = nom de la table
  • * (string)$Field = nom du champ
  • * (bool)$Strict = si vaut true, recherche la valeur exacte
  • * Return : (bool)true si la valeur a été trouvée, sinon false
  • **/
  • public function InTable($Needle, $Table, $Field, $Strict = false)
  • {
  • //On recherche la valeur $Needle dans la table $Table et le champ $Field
  • $result = $this->GetFrom($Table, $Field, false, $Field.'` LIKE "'.($Strict?$Needle:'%'.$Needle.'%').'"');
  • //S'il y a au moins un resultat, on retourne true sinon false
  • return count($result) ? true : false;
  • }
  • /** Fonction LastInsertId
  • # Desc : Retourne l'id du dernier enregistrement inseré
  • * Params : None
  • * Return : (int)ID du dernier enregistrement inséré
  • **/
  • public function LastInsertId()
  • {
  • //Requête permettant de récupérer le dernier id inséré
  • $sql = 'SELECT LAST_INSERT_ID() as last_id';
  • $query = $this->connection->query($sql);
  • //On retourne le résultat de la requête
  • return $query->fetchColumn();
  • }
  • /** Fonction Query
  • * Desc : Execute une requête SQL
  • * Params : (string)$sql = Requête SQL
  • * Return : (int)Nombre d'enregistrements affectés par la requête
  • **/
  • public function Query($Sql)
  • {
  • //On enregistre la requête pour pouvoir la ressortir au besoin
  • $this->sql = $Sql;
  • try {
  • //On execute la requête
  • $query = $this->connection->exec($this->sql);
  • //Si une erreur s'est produite
  • if (($error = $this->GetError()) !== false)
  • {
  • //On annule la transaction
  • $this->RollBackTransaction();
  • //On retourne l'erreur
  • Throw new Exception($error);
  • }
  • else
  • //Sinon on renvoie le résultat de la requête (nombre d'enregistrements affectés)
  • return $query;
  • } catch(Exception $e) {
  • //On affiche le message d'erreur
  • echo 'Une erreur s\'est produite lors de la validation de la requ&ecirc;te : <b>'.$e->getMessage().'</b>';
  • //On retourne false
  • return false;
  • }
  • }
  • /** Fonction Query2Array
  • * Desc : Retourne sous forme de tableau le résultat d'une requête de sélection
  • * Params : (string)$sql = Requête SQL
  • * Return : (array)Résultat de la requête, sinon false en cas d'erreur
  • **/
  • public function Query2Array($Sql)
  • {
  • //On enregistre la requête pour pouvoir la ressortir au besoin
  • $this->sql = $Sql;
  • try {
  • //On execute la requête
  • $query = $this->connection->query($this->sql);
  • //Si un erreur s'est produite
  • if (($error = $this->GetError()) !== false)
  • {
  • //On retourne l'erreur
  • Throw new Exception($error);
  • }
  • else
  • //Sinon on retourne le tableau de résultat
  • return $query->fetchAll(PDO::FETCH_ASSOC);
  • } catch (Exception $e) {
  • //On affiche le message d'erreur
  • echo 'Erreur de requ&ecirc;te SQL : <b>'.$e->getMessage().'</b><br />Rappel de la requ&ecirc;te : <b>'.$this->sql.'</b>';
  • //On retourne false
  • return false;
  • }
  • }
  • /** Fonction RollBackTransaction
  • * Desc : Annule une transaction MySQL
  • * Params : None
  • * Return : Void
  • **/
  • public function RollBackTransaction()
  • {
  • //Si une transaction est active
  • if ($this->ActiveTransaction)
  • {
  • //On l'annule
  • if ($this->connection->rollBack())
  • //Et on modifie le tag de transaction
  • $this->ActiveTransaction = false;
  • }
  • }
  • /** Fonction GetError
  • * Desc : Renvoi le dernier message d'erreur formaté
  • * Params : None
  • * Return : (string)Message d'erreur
  • **/
  • private function GetError()
  • {
  • //On récupère les informations sur l'erreur
  • $ErrorMessage = $this->connection->errorInfo();
  • //S'il n'y a pas d'erreur
  • if ($ErrorMessage[0] === '00000')
  • //On retourne false
  • return false;
  • else
  • //Sinon on retourne le message d'erreur formaté
  • return "<p>Error : ".$ErrorMessage[0]." ".$ErrorMessage[1]." ".$ErrorMessage[2]."<br />SQL : ".$this->sql."</p>";
  • }
  • /** Fonction MakeSQLPart
  • * Desc : Constructeur de requête SQL
  • * Params : (string)Section à créer (SELECT, FROM, WHERE, ORDER BY, GROUP BY, LIMIT)
  • * (string|array)Contenu de la section à créer
  • * Return : (string)Partie de la requête demandée, sinon false
  • **/
  • private function MakeSQLPart($Part, $Values)
  • {
  • //Sections disponibles à la création
  • $AllowedParts = array('SELECT', 'FROM', 'WHERE', 'ORDER BY', 'GROUP BY', 'LIMIT');
  • //Initialisation de la requête
  • $Sql = '';
  • //Si la section demandée fait bien partie des sections disponibles
  • if (in_array($Part, $AllowedParts))
  • {
  • //Si le contenu n'est pas vide
  • if (!empty($Values))
  • //On créer la requête en ajoutant la section demandée
  • $Sql .= ' '.strtoupper($Part).' ';
  • else
  • //Sinon le contenu est vide alors on retourne une chaine vide
  • return $Sql;
  • //Si le contenu est un tableau
  • if (is_array($Values))
  • {
  • //On prépare le séparateur
  • //Si la section demandée est WHERE
  • if ($Part == 'WHERE')
  • //Le séparateur sera AND
  • $separator = ' AND ';
  • else
  • //Sinon ce sera une virgule
  • $separator = ', ';
  • //Clé pour connaitre la position dans le tableau
  • $Key = 1;
  • //On parcours le tableau
  • foreach ($Values as $Value)
  • {
  • //On ajoute la valeur courante du tableau
  • $Sql .= $Value;
  • //Si nous ne sommes pas à la fin du tableau
  • if (($Key) != count($Values))
  • //On ajoute le séparateur
  • $Sql .= $separator;
  • //On incrémente de un pour l'élément suivant
  • $Key++;
  • }
  • }
  • else
  • //Sinon le contenu est une chaine alors on l'ajoute directement à notre morceau de requête
  • $Sql .= $Values;
  • //Et on retourne le morceau de requête construit
  • return $Sql;
  • }
  • else
  • //Sinon si la section demandées n'est pas dans les sections disponibles, on retourne false
  • return false;
  • }
  • /** Fonction GetLastSql
  • * Desc : Retourne la dernière requête exécutée.
  • * Params : None
  • * Return : (string)Dernière requête SQL executée
  • **/
  • public function GetLastSql () {
  • return $this->sql;
  • }
  • }
  • ?>
<?php
/**
*	Classe de manipulation de base MySQL
*	
*	Dernière mise à jour : 17/09/2010
**/
class Db
{
	private $connection = false;				//Instance PDO
	
	private $ActiveTransaction = false;			//Flag indiquant si une transaction a été démarrée
	
	private $sql = '';							//Dernière requête SQL executée
	
	/**	Fonction Constructeur
	*	Desc 	:	Initialise la connexion
	*	Params 	:	(string)$Serveur = Adresse du serveur MySQL
	*				(string)$Utilisateur = Nom d'utilisateur de la base MySQL
	*				(string)$MotDePasse = Mot de passe MySQL
	*				(string)$BaseDeDonnees = Nom de la base de données
	*	Return	:	Void
	**/
	public function __construct($Serveur, $Utilisateur, $MotDePasse, $BaseDeDonnees)
	{
		try {
			//On instancie l'objet PDO et on se connecte à la base
			$this->connection = new PDO('mysql:host='.$Serveur.';dbname='.$BaseDeDonnees, $Utilisateur, $MotDePasse, array(PDO::ATTR_PERSISTENT => true));
		} catch (PDOException $e) {
			//En cas d'erreur, on affiche un message avec l'erreur retournée
			echo 'Connexion &eacute;chou&eacute;e : <b>'.$e->getMessage().'</b>';
		}
	}
	
	/** Fonction BeginTransaction
	*	Desc	:	Démarre une transaction MySQL
	*	Params	:	None
	*	Return	:	Void
	**/
	public function BeginTransaction()
	{
		//S'il n'existe pas de transaction active, on l'active
		if (!$this->ActiveTransaction)
			$this->ActiveTransaction = $this->connection->beginTransaction();
	}
	
	/** Fonction CommitTransaction
	*	Desc	:	Valide une transaction MySQL
	*	Params	:	None
	*	Return	:	(bool)true si la validation s'est bien passée, sinon false
	**/
	public function CommitTransaction()
	{
		try {
			//Si une transaction est active
			if ($this->ActiveTransaction)
			{
				//On la valide
				if ($this->connection->commit())
				{
					//Il n'y a plus de transaction active
					$this->ActiveTransaction = false;
					//La validation s'est bien passée donc on retourne true
					return true;
				}
				else
				{
					//Si la validation retourne false, on créé une erreur
					Throw new Exception('La transaction n\'a pas pu &ecirc;tre valid&eacute;e.<br />'.$this->GetError());
				}
			} else {
				//S'il n'y a pas de transaction active, on créé une erreur
				Throw new Exception('Aucune transaction active');
			}
		} catch (Exception $e) {
			//En cas d'erreur, on affiche un message avec l'erreur retournée
			echo 'Impossible de valider la transaction : <b>'.$e->getMessage().'</b>';
			return false;
		}
	}
	
	/** Fonction GetFrom
	*	Desc	: 	Retourne un tableau contenant les enregistrements selon les conditions spécifiées
	*	Params	: 	(string|array)$Table = Table SQL
	*				(string|array)$Fields = Champ(s) à retourner
	*				(string|array)$Where = Conditions WHERE
	*				(string|array)$Order = Champ(s) de tri
	*				(string|array)$GroupBy = Champ(s) à grouper
	*				(string)$Limit = Limitation de la requête
	*	Return	:	(array)résultat de la requête
	**/
	public function GetFrom($Table, $Fields = false, $Order = false, $Where = false, $GroupBy = false, $Limit = false)
	{
		//On initialise une nouvelle requête
		$Sql = '';
		//On créé la requête section par section
		//Section SELECT
		$Sql .= $this->MakeSQLPart('SELECT', $Fields?$Fields:'*');
		//Section FROM
		$Sql .= $this->MakeSQLPart('FROM', $Table);
		//Section WHERE
		$Sql .= $this->MakeSQLPart('WHERE', $Where);
		//Section ORDER BY
		$Sql .= $this->MakeSQLPart('ORDER BY', $Order);
		//Group By s'il y a
		$Sql .= $this->MakeSQLPart('GROUP BY', $GroupBy);
		//Limit s'il y a
		$Sql .= $this->MakeSQLPart('LIMIT', $Limit);
		//On retourne le tableau de résultat renvoyé par la fonction Query2Array();
		return $this->Query2Array($Sql);
	}
	
	/** Fonction GetValue
	*	Desc	: 	Retourne une valeur recherchée dans la base
	*	Params	: 	(string)$Table = Table SQL
	*				(string|array)$Field = Champ recherché
	*				(string|array)$Where = Critère WHERE
	*	Return	:	(string)valeur trouvée, sinon false
	**/
	public function GetValue($Table, $Field, $Where)
	{
		//On requête pour obtenir la valeur recherchée
		$result = $this->GetFrom($Table, 'DISTINCT('.$Field.')', false, $Where);
		//Si la requête a renvoyé un résultat
		if (count($result) === 1) {
			//On vérifie si la variable $Field a été renseigné avec la table
			//Du type matable.monchamp
			//On récupère la position du point
			$PositionPoint = strpos($Field, '.');
			//Et on déduit le nom du champ
			$FieldName = substr($Field, $PositionPoint ? $PositionPoint + 1 : 0);
			//On retourne la valeur recherchée
			return $result[0][$FieldName];
		} else {
			//Sinon il n'y a aucun ou plus d'un résultat donc on retourne false
			//Car on veut retourner une et une seule valeur
			return false;
		}
	}
	
	/** Fonction InTable
	*	Desc	:	Indique si une valeur est contenue par la table et le champ donné
	*	Params	:	(string)$Needle = valeur recherchée
	*				(string)$Table = nom de la table
	*				(string)$Field = nom du champ
	*				(bool)$Strict = si vaut true, recherche la valeur exacte
	*	Return	:	(bool)true si la valeur a été trouvée, sinon false
	**/
	public function InTable($Needle, $Table, $Field, $Strict = false)
	{
		//On recherche la valeur $Needle dans la table $Table et le champ $Field
		$result = $this->GetFrom($Table, $Field, false, $Field.'` LIKE "'.($Strict?$Needle:'%'.$Needle.'%').'"');
		//S'il y a au moins un resultat, on retourne true sinon false
		return count($result) ? true : false;
	}
	
	/**	Fonction LastInsertId
	#	Desc	:	Retourne l'id du dernier enregistrement inseré
	*	Params	:	None
	*	Return	:	(int)ID du dernier enregistrement inséré
	**/
	public function LastInsertId()
	{
		//Requête permettant de récupérer le dernier id inséré
		$sql = 'SELECT LAST_INSERT_ID() as last_id';
		$query = $this->connection->query($sql);
		//On retourne le résultat de la requête
		return $query->fetchColumn();
	}
	
	/**	Fonction Query
	*	Desc	:	Execute une requête SQL
	*	Params	:	(string)$sql = Requête SQL
	*	Return	:	(int)Nombre d'enregistrements affectés par la requête
	**/
	public function Query($Sql)
	{
		//On enregistre la requête pour pouvoir la ressortir au besoin
		$this->sql = $Sql;
		
		try {
			//On execute la requête
			$query = $this->connection->exec($this->sql);
			//Si une erreur s'est produite
			if (($error = $this->GetError()) !== false)
			{
				//On annule la transaction
				$this->RollBackTransaction();
				//On retourne l'erreur
				Throw new Exception($error);
			}
			else
				//Sinon on renvoie le résultat de la requête (nombre d'enregistrements affectés)
				return $query;
		} catch(Exception $e) {
			//On affiche le message d'erreur
			echo 'Une erreur s\'est produite lors de la validation de la requ&ecirc;te : <b>'.$e->getMessage().'</b>';
			//On retourne false
			return false;
		}
	}
	
	/** Fonction Query2Array
	*	Desc	:	Retourne sous forme de tableau le résultat d'une requête de sélection
	*	Params	: 	(string)$sql = Requête SQL
	*	Return	:	(array)Résultat de la requête, sinon false en cas d'erreur
	**/
	public function Query2Array($Sql)
	{
		//On enregistre la requête pour pouvoir la ressortir au besoin
		$this->sql = $Sql;
		
		try {
			//On execute la requête
			$query = $this->connection->query($this->sql);
			//Si un erreur s'est produite
			if (($error = $this->GetError()) !== false)
			{
				//On retourne l'erreur
				Throw new Exception($error);
			}
			else
				//Sinon on retourne le tableau de résultat
				return $query->fetchAll(PDO::FETCH_ASSOC);
		} catch (Exception $e) {
			//On affiche le message d'erreur
			echo 'Erreur de requ&ecirc;te SQL : <b>'.$e->getMessage().'</b><br />Rappel de la requ&ecirc;te : <b>'.$this->sql.'</b>';
			//On retourne false
			return false;
		}
	}
	
	/** Fonction RollBackTransaction
	*	Desc	: 	Annule une transaction MySQL
	*	Params	:	None
	*	Return	:	Void
	**/
	public function RollBackTransaction()
	{
		//Si une transaction est active
		if ($this->ActiveTransaction)
		{
			//On l'annule
			if ($this->connection->rollBack())
			//Et on modifie le tag de transaction
				$this->ActiveTransaction = false;
		}
	}
	
	/** Fonction GetError
	*	Desc	:	Renvoi le dernier message d'erreur formaté
	*	Params	:	None
	*	Return	:	(string)Message d'erreur
	**/
	private function GetError()
	{
		//On récupère les informations sur l'erreur
		$ErrorMessage = $this->connection->errorInfo();
		//S'il n'y a pas d'erreur
		if ($ErrorMessage[0] === '00000')
			//On retourne false
			return false;
		else
			//Sinon on retourne le message d'erreur formaté
			return "<p>Error : ".$ErrorMessage[0]." ".$ErrorMessage[1]." ".$ErrorMessage[2]."<br />SQL : ".$this->sql."</p>";
	}
	
	
	/** Fonction MakeSQLPart
	*	Desc	:	Constructeur de requête SQL
	*	Params	:	(string)Section à créer (SELECT, FROM, WHERE, ORDER BY, GROUP BY, LIMIT)
	*				(string|array)Contenu de la section à créer
	*	Return	:	(string)Partie de la requête demandée, sinon false
	**/
	private function MakeSQLPart($Part, $Values)
	{
		//Sections disponibles à la création
		$AllowedParts = array('SELECT', 'FROM', 'WHERE', 'ORDER BY', 'GROUP BY', 'LIMIT');
		//Initialisation de la requête
		$Sql = '';
		//Si la section demandée fait bien partie des sections disponibles
		if (in_array($Part, $AllowedParts))
		{
			//Si le contenu n'est pas vide
			if (!empty($Values))
				//On créer la requête en ajoutant la section demandée
				$Sql .= ' '.strtoupper($Part).' ';
			else
				//Sinon le contenu est vide alors on retourne une chaine vide
				return $Sql;
			
			//Si le contenu est un tableau
			if (is_array($Values))
			{
				//On prépare le séparateur
				//Si la section demandée est WHERE
				if ($Part == 'WHERE')
					//Le séparateur sera AND
					$separator = ' AND ';
				else
					//Sinon ce sera une virgule
					$separator = ', ';
				//Clé pour connaitre la position dans le tableau
				$Key = 1;
				//On parcours le tableau
				foreach ($Values as $Value)
				{
					//On ajoute la valeur courante du tableau
					$Sql .= $Value;
					//Si nous ne sommes pas à la fin du tableau
					if (($Key) != count($Values))
						//On ajoute le séparateur
						$Sql .= $separator;
					//On incrémente de un pour l'élément suivant
					$Key++;
				}
			}
			else
				//Sinon le contenu est une chaine alors on l'ajoute directement à notre morceau de requête
				$Sql .= $Values;
			//Et on retourne le morceau de requête construit
			return $Sql;
		}
		else
			//Sinon si la section demandées n'est pas dans les sections disponibles, on retourne false
			return false;
	}
	
	
	/** Fonction GetLastSql
	*	Desc	:	Retourne la dernière requête exécutée.
	*	Params	:	None
	*	Return	:	(string)Dernière requête SQL executée
	**/
	public function GetLastSql () {
		return $this->sql;
	}
}
?>

 Conclusion

Je pense que la classe est suffisamment commentée pour que je n'ai pas à vous montrer un exemple d'utilisation.
Mais si vous avez des questions, n'hésitez pas. J'y répondrai avec plaisir.


 Sources du même auteur

GÉNÉRATEUR DE LISTE DÉROULANTE
AFFICHAGE D'UN TABLEAU HTML À PARTIR D'UN ARRAY

 Sources de la même categorie

Source avec Zip ORM : DAO, ACTIVERECORD ET DBLIST par Reldan
Source avec une capture CET EXTRAIT PERMET D'AJOUTER DANS UN TABLEAU UNE AGRÉGATION ... par Denis007
EXPORT DE BASE AU FORMAT CSV par remib74
Source avec Zip RECHERCHE DES DOUBLONS DANS UNE TABLE MYSQL EN SÉLECTIONNANT... par aladec2007
[CRON] INSERT ON DUPLICATE KEY UPDATE par pierreSabatier

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture CONVERTIR BASE FIREBIRD EN MYSQL par castelfrederic29
Source avec Zip Source avec une capture DBOC - V3.1 [AJAX][PHP5] par Morphinof
Source avec Zip [PHP5.2] CLASSE PDO par hornetbzz
Source avec Zip CLASSE SQL par benjycorp
Source avec Zip ABSTRACTION PDO par dorian91

Commentaires et avis

Commentaire de fenoril le 17/09/2010 19:45:17

Bonjour !

N'est-ce pas un peu dommage de ne pas utiliser les requètes préparées afin d'obtenir une sécurisations satisfaisante en plus de l'automatisation ? Y aurait-il une contrindication que je n'aurais pas compris ? (Ce n'est aucunement de l'ironie, je suis pas assez fort pour voir tous les détails...)

Ceci dit, je ne vois pas l'intéret de la décomposition des requètes sql... Qu'y trouves-tu ?

Par ailleurs merci pour le partage de code.

Commentaire de neigedhiver le 18/09/2010 01:33:50

Salut,

Le code est propre, documenté, tu as choisi d'utiliser PDO : que des bons points.
Cependant, je note, vite-fait, des erreurs de conception :

1/ Dans le constructeur, tu mets un bloc try...catch : même si ça fonctionne (heureusement !) ce n'est pas très correct, dans la conception : les exceptions n'ont pas de raison, fondamentalement, d'être traitées dans une classe comme celle-ci. Ta classe est une surcouche de PDO (on y reviendra plus tard) ; PDO lève des exceptions => pourquoi ta classe les intercepterait-elle ? La seule raison valable serait : les traiter de manière plus approfondie (log dans un fichier, utilisation d'un cache, etc). Or, on ne peut pas dire qu'un vulgaire echo (pardon pour lui) soit plus approfondi qu'une véritable gestion d'exception. Conclusion : tu peux tout à fait attraper une PDOException, si tu lèves une exception perso DbException (ce qui resterait cohérent). Donc au lieu de faire un echo, lève une exception à toi : c'est à l'utilisateur de décider comment il les gère, pas à toi de lui imposer l'affichage d'un texte alors que si ça se trouve, i la décidé de ne rien faire afficher du tout par son script (genre je traite les données d'un formulaire, je n'affiche rien, puis je redirige avec header()... sauf que paf, tu as forcé l'envoi des entêtes HTTP, le script plante complètement).

2/ Comme je le disais, ta classe est une curcouche de PDO. Pourquoi ? Pourquoi ne pas simplement étendre PDO ? Tu ne fais même pas un véritable wrapper, puisque tu limites les méthodes disponibles... Pour faire un véritable wrapper, il faudrait au minimum utiliser la méthode magique __call() pour pouvoir utiliser les méthodes de PDO. Ta classe ne permet pas de se passer des méthodes de PDO que tu ne remplaces pas...

3/ Ta méthode Query2Array() me paraît inutile en plus d'être mal codée. De même que pour le constructeur, tu devrais lever une nouvelle exception plutôt que simplement intercepter celle qui se présente et afficher un message d'erreur. Qui plus est, si une erreur SQL se produit, tu lèves une exception standard : ce n'est pas rendre service à l'utilisateur qui ne va plus savoir quand intercepter des exceptions ni lesquelles peuvent être attrapées.
Par ailleurs, PDO permet d'itérer sur les résultats PDOStatement, ce que ne permettait pas l'extension mysql sans une classe supplémentaire : pourquoi tout récupérer dans un tableau ? C'est non seulement superflu, mais surtout non performant : PDO va itérer une première fois sur le résultat pour remplir le tableau, puis l'utilisateur va itérer sur le tableau pour traiter les résultats (et il est capable d'itérer encore pour les afficher... sisi, ça arrive, j'en ai vus).


Bon, d'autres détails qui me gênent un peu...

Dans ta méthode makeSQLPart() :
#  foreach ($Values as $Value)
# {
# //On ajoute la valeur courante du tableau
# $Sql .= $Value;
# //Si nous ne sommes pas à la fin du tableau
# if (($Key) != count($Values))
# //On ajoute le séparateur
# $Sql .= $separator;
# //On incrémente de un pour l'élément suivant
# $Key++;
# }

Pouah, c'est répugnant... dire qu'on peut faire ça en une ligne (de manière certainement plus optimisée en terme de performances) en une seule ligne avec implode() (et en plus c'est bien plus lisible !).

Dans la méthode InTable() :
return count($result) ? true : false;
Je te propose :
return (bool) $this->GetFrom($Table, $Field, false, $Field.'` LIKE "'.($Strict?$Needle:'%'.$Needle.'%').'"');

D'une manière générale, essaie de proscrire la gestion d'erreur dans la classe avec des echo : une classe permet à l'utilisateur de modulariser son code ; il ne FAUT PAS l'obliger à afficher quelque chose s'il ne le souhaite pas.
Pour ta méthode GetError(), tu devrais simplement retourner le message d'erreur, avec le minimum de mise en forme. Ou alors, laisse l'utilisateur modifier le masque, via une propriété avec un setter, plutôt que de lui imposer un formatage html avec <p> et <br /> : si je veux afficher ça dans une liste <ul> ? Ou dans un <div> avec un id spécifique, pour le mettre en forme avec un CSS ?

Bon... Ne vois pas dans mon commentaire une critique destructrice de ta source : l'intention est louable, c'est plutôt bien codé et surtout très clair (ce qui est rare quand même !!). Vois-y plutôt un peu de matière pour pouvoir améliorer ta source et la rendre plus intéressante (y compris pour toi). Je te donne des conseils qui doivent également te permettre de coder de manière plus souple et modularisable, en séparant autant que possible l'affichage des données de leur traitement. Ta classe ne sert pas à afficher, juste à traiter : laisse l'utilisateur afficher comme il l'entend.
Et n'hésite pas à utiliser des classes d'exceptions personnalisées qui pourront réellement servir à l'utilisateur (parce que c'est à lui qu'il faut penser, pas au développeur).

Bonne continuation !

Commentaire de neigedhiver le 18/09/2010 01:37:11

Ah une chose à laquelle je pensais depuis le début de la rédaction de mon commentaire et que j'ai perdue en cours de route...
Pour reprendre ce que dis Fenoril, ta décomposition de requêtes m'étonne : c'est comme si tu mélangeais ORM et DAO dans une sourcouche de PDO... Un joyeux mélange pas forcément facile à manipuler avec cette classe, en l'état...

Commentaire de Vince66 le 20/09/2010 11:01:55

Salut à vous deux,

Tout d'abord merci d'avoir pris le temps d'étudier mon code et de rédiger une critique très constructive :)

Pour te répondre Neigedhiver sur la gestion des erreurs, j'ai commencé à développer la classe pour des besoins perso et ça m'allait bien d'avoir un retour immédiat en cas d'erreur. Mais je me rends compte effectivement qu'à partir du moment où je la partage, il est plus logique de séparer la gestion des erreurs et la gestion des données pour qu'elle soit modulaire. Je vais travailler dessus afin d'aller dans ce sens.

Pourquoi ne pas avoir étendu PDO ? C'est surement très bête mais tout simplement parce que je n'y avais pas pensé. C'est aussi ce que je recherchais en déposant ma source sur CodesSources : avoir des retours constructifs qui me permettent de l'améliorer et corriger des points auxquels je n'avais pas pensé :)
Donc merci.

Pour la méthode Query2Array, le but était de simplifier le format de sortie des données afin de parcourir celles-ci avec un simple for ou foreach. En revanche, je comprends tout à fait la problématique des performances dégradées dues au double parcours des données.

Holala tu as entièrement raison pour le bout de code que tu cites, je n'avais absolument pas pensé au implode. Mea Culpa !

Merci pour la méthode InTable, en effet c'est plus simple.

Enfin pour vous répondre à tous les deux, dans la décomposition de requête, l'idée était encore une fois de simplifier la construction des diverses requêtes. Cependant, j'admets que cela manque de souplesse lorsque l'on veut faire des requêtes plus complexes. C'était une expérimentation très maladroite, j'avoue.

Rassure toi, j'aurais du mal à prendre pour "destructive" une critique aussi détaillée et argumentée ;)
Une remarque du style "C'est nul ! Retourne faire du Word", je l'aurais moins bien pris c'est sûr :D
Je vais prendre en compte vos remarques et essayer de faire une classe plus cohérente.
Merci encore !

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Formulaire avec select et update de bdd mysql [ par arnold002 ] Bonjour &#224; tous,J'ai un formulaire qui contient 2 champs de type select : classe et annee.Je veux associer chaque classe &#224; chaque ann&#233;e passage de variables de form vers bdd mysql [ par arnold002 ] Bonjour,Mon probl&#232;me n'avance pas...Mon form contient 2 champs select for($i<FONT color=#008000 s Problème affichage BD multiples [ par ekipage2 ] Bonjour,j'ai plusieurs BD : eleve / matières / et exercicesLorque l'élèv se connecte, il peut afficher la liste des exercices correspondants à sa clas Recherche mysql [ par simon0000 ] salut tous le monde ,j'ai une table mysql nom&#233;&nbsp;ecole ou il ya Retour des données d'une classe MySQL [ par Jerem_ ] Salut, Depuis ce matin, j'asseye de coter une classe MySQL pour mon site. La classe marche tr&#232;s bien quand je fait une requete INSERT, etc .. M Bug dans une double liste [ par stu76 ] Bonjour, Malalam m'a donné des infos hier sur les doubles liste, et je le remercie car ca ma été super utile. J'ai presque résolu le prob sauf que je Problème de code [ par stu76 ] Bonjour tout le monde ,Voil&#224; je planche sur un programme scolaire et j'ai un gros prob, je travaille sur un programme qui utilise trois base de d Problème d'utilisation d'une classe MySQL du site [ par tataye ] Bonjour,Je suis en train de faire des tests avec la classe SQL  de FhX (source N°33135) et je rencontre actuellement quelques difficultés.J'ai fait un appeller de fonction "interclasses" [ par DDelec24 ] Bonjour.Je suis bloqué depuis hier sur un problème pour appeller une fonction.Pour résumé:Je possède une classe mysql pour gérer tout ce qui est reque Classe Connexion.php la plus simple possible .... [ par Tartuffe245 ] Bonjour à tous,J'ai créé une classe connexion pour mon site internet et il se trouve que j'ai une erreur qui revient souvent mais je ne sais pas comme


Nos sponsors


Sondage...

CalendriCode

Mai 2012
LMMJVSD
 123456
78910111213
14151617181920
21222324252627
28293031   

Consulter la suite du CalendriCode

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,577 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales