Danygras

Sommaire - interface sql.class.php - mysqlext.class.php - mysqliu.class.php - mypdo.class.php

Abstraction SQL en PHP

<?php

/*******
*
*	Classe d'acces simplifié SQL
*	Last modified: march 28, 2014
*	©The P'tit Prince
*   source : http://codes-sources.commentcamarche.net/source/100478-class-sql
*
*   v2 pifou25 pour interface SQL - dec 2014
********/


class mypdo implements sql {

	private $config;		// Configuration de connection SQL
	private $connect;		// Connection a la base
	private $debug = false;
	private $dateformat = '%d-%m-%y à %H:%i:%s'; /* Mettre ça dans les tpl */
	private $dbdecal = '00:00:00';
	private $prebdd = '';

	private $query = null;			// Requete en cours
	private $stmt = null;			// PDO::statement en cours
	private $log = false; // objet log.class.php

	private $errno = '';		// Enregistre la derniere erreur
	private $err = 0;		// Enregistre la derniere erreur
	private $records;		// Enregistre le nombre d'enregistrements de la dernière requête
	private $vars;

	public $queries = array(); // infos pour debug
	
/*******
*
*	Constructeur
*
********/


	function __construct($host,$login,$pass,$base){

		try{
			$this->connect = new PDO(
				"mysql:host=$host; dbname=$base",
				$login,
				$pass
			);
			$this->connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
			
		}catch(PDOException $error){
			// Faire class debug
			$this->err = 'Échec lors de la connexion : ' . $error->getMessage();
			echo $this->err;
			die($this->err);
		}
		
		$this->connect->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
		$this->connect->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
		$this->connect->setAttribute(PDO::ATTR_ORACLE_NULLS, PDO::NULL_EMPTY_STRING);
		//$this->connect->exec("SET NAMES utf8");
	}


	/**
	 * mode debug 
	 * @param $debug booleen
	 * @return void
	 */
	function set_debug($debug) 
	{
		$this->debug = $debug;
	}
	
	/**
	 * décalage horaire pour les dates
	 * @param $decal String au format HH:mm:ss (ex: '00:00:00')
	 * @return void
	 */
	function set_dbdecal($var)
	{
		$this->dbdecal = $var;
	}

	/**
	 * ajouter un préfixe à toutes les tables
	 * @param $var String
	 * @return void
	 */
	function set_prebdd($var)
	{
		$this->prebdd = $var;
	}
	
	/**
	 * selon les BDD l'échappement de caractère est spécifique
	 * PDO->quote ajoute les quote en début et fin aussi = ne convient pas.
	 * addslashes = faute de mieux
	 *
	 * @param $string String à échapper
	 * @return String
	 */
	function escape_string($string)
	{
		return addslashes($string);
	}

	/**
	 * 'analyser' une requête SQL. permet des remplacements (format date ou décalage, préfixe...)
	 * @param $req String
	 * @return String
	 */
	function parse_query($req)
	{
		/* le DATE_FORMAT c'était long a écrire */
		if($this->dbdecal != '00:00:00'){
			$req = preg_replace("/_UDATE_FORMAT\((.*?)\)/i","DATE_FORMAT(FROM_UNIXTIME($1) + INTERVAL '".$this->dbdecal."' HOUR_SECOND,'".$this->dateformat."')",$req);
			$req = preg_replace("/_DATE_FORMAT\((.*?)\)/i","DATE_FORMAT($1 + INTERVAL '".$this->dbdecal."' HOUR_SECOND,'".$this->dateformat."')",$req);
		}else{
			$req = preg_replace("/_UDATE_FORMAT\((.*?)\)/i","FROM_UNIXTIME($1,'".$this->dateformat."')",$req);
			$req = preg_replace("/_DATE_FORMAT\((.*?)\)/i","DATE_FORMAT($1,'".$this->dateformat."')",$req);
		}
		/* TODO ? ajouter le parse pour le préfixe des tables */
		if(!empty($this->prebdd))
			$req = preg_replace('/(INTO|FROM|UPDATE)\s+`?(\w+)/ig', '$1 `'.$this->prebdd.'$2`', $req);
		return $req;
	}

	/**
	 * dernier code erreur (ou zéro si la dernière requête est OK)
	 * @return Int
	 */
	function errno()
	{
		return $this->errno;
	}

	/**
	 * dernier message d'erreur
	 * @return String
	 */
	function error()
	{
		return $this->err;
	}

	/**
	 * dernier id inséré
	 * @return Int
	 */
	function insert_id()
	{
		if($this->stmt != null)
			return $this->stmt->lastInsertId();
	}

	/**
	 * nb de lignes modifiées par la dernière requête
	 * @return Int
	 */
	function affected_rows()
	{
		if($this->stmt != null)
			return $this->stmt->rowCount();
	}

	/**
	 * rechercher la n'ième ligne et le n'ième champs
	 * @param $res : un objet ''PDO::statement''
	 * @param $row Int :  la ligne à chercher
	 * @param $field String ou Int : indice du champs à chercher. Si omis, renvoie la ligne complète
	 * @return mixed (String ou Array)
	 */
	function result($res, $row, $field = NULL)
	{
		$ret = $res->fetch(PDO::FETCH_BOTH, PDO::FETCH_ORI_ABS, $row);
		if($field != null && isset($ret[$field]))
			return $ret[$field];
		else
			return $ret;
	}
	
	/**
	 * compter le nb de lignes de la ressource
	 * @param $res : objet ''result''
	 * @return Int
	 */
	function num_rows($res)
	{
		return $this->records;
	}
	
	/**
	 * exécuter la requête 
	 * @param $req : requête SQL
	 * @param $explain : ajouter les explications SQL (requête EXPLAIN)
	 * @return mixed (booleen, objet recordset, ''result'' ...)
	 */
	function query($req, $explain = true)
	{
		return $this->prepareQuery($req, null, $explain);
	}

	/**
	 * libérer un objet
	 * @param $res : objet ''result''
	 * @return booleen
	 */
	function free_result($res)
	{
		return $res->closeCursor();
	}
	
	/**
	 * log une erreur SQL (dans un fichier ou...)
	 * @param $req String
	 * @return String
	 */
	function log_error($req)
	{
		$text = '**** '.date("H:i:s d/m/Y")." ***\n";
		$text .= $this->errno." | ".print_r( $this->err, true) ."\n";
		$text .= $this->errno." | ".$req."\n\n";
		$this->log($text);
		return $text;
	}

	/**
	 * log du texte (dans un fichier ou...)
	 * @param $text String
	 * @return void
	 */
	function log($text) {
		if($this->log === false)
			$this->log = new log(SITE_DIR."cache/log/mysql_".date("d_m_Y").".log", false, false);
		$this->log->text($text);
	}

	/**
	 * exécuter la requête + renvoyer la 1ère ligne uniquement, sous forme d'un tableau
	 * @param $req String
	 * @return Array
	 */
	function make_array_result($req)
	{
		if($res = $this->query($req))
			return $res->fetch();
		else
			return false;
	}

	/**
	 * exécuter la requête + renvoyer sous forme d'un tableau
	 * @param $req String
	 * @param $explain : ajouter les explications SQL (requête EXPLAIN)
	 * @return Array
	 */
	function make_array($req, $explain = true)
	{
		if($stmt = $this->query($req)){
			$res = $stmt->fetchAll();
			$this->records = count($res);
			return $res;
		}
		else
			return false;
	}

	/**
	 * exécuter la requête + renvoyer sous forme d'un tableau indexé, la clé du tableau est le champ $idx
	 * @param $req String
	 * @param $idx String : champs à utiliser comme index du tableau
	 * @param $explain : ajouter les explications SQL (requête EXPLAIN)
	 * @return Array
	 */
	function index_array($req, $idx = false, $explain = true)
	{
		if($idx === false)
			return $this->make_array($req, $explain);

		$var = array();
		if($stmt = $this->query($req))
			while($row = $stmt->fetch())
				$var[$row[$idx]] = $row;
		
		$this->records = count($var);
		return $var;
	}


	/**
	 * exécuter la requête + renvoyer la valeur de la 1ère ligne
	 * remarque : idem que result($sql, 0, $field);
	 * @param $req String
	 * @param $field String : le nom du champs à rendre
	 * @return mixed (String ou Int)
	 */
	function get_result($sql, $field)
	{
		if($stmt = $this->query($sql))
		{
			$res = $stmt->fetch();
			return isset($res[$field]) ? $res[$field] : false;
		}
		return false;
	}

	/**
	 * fermeture de la connexion : inutile en PDO
	 * @return booleen
	 */
	function close(){
		unset($this->connect);
		return true;
	}

	

/*******
*
*	Autres Fonctions Publiques - spécifique mypdo, hors interface SQL
*
********/

	// prépare et execute une requette SQL avec des paramètres - ou pas
	// rend un objet PDOStatement
	// spécifique PDO
	public function prepareQuery($query,$vars=NULL,$explain=true){

		$this->query = $this->parse_query($query);
		$this->stmt = $this->connect->prepare($this->query);

		try{
			$res = $this->stmt->execute($vars);
		}catch(Exception $error){
			$this->err = $error->getMessage();
			echo $this->err;
			return false;
		}
		$this->err = $this->stmt->errorInfo();
		$this->errno = $this->stmt->errorCode();

		// si debug ajouter des infos
		if($this->debug && $explain) {

			$this->queries[] = array('req' => $this->query,
				'errno'=>$this->errno,
				'err'	=> $this->err,
				'time'=> 0, // $this->getmicrotime()-$debut,
				// 'infos' => mysql_info(),
				'num' => 0
				);

		}

		if ($res)
			return $this->stmt;
		else {
			$this->log_error($this->query . "\n" . print_r($vars, true));
			return false;
		}
	}

	// utilité des fonctions suivantes ??
	
	
	// Permet d'insérer une nouvelle entrée dans la base
	public function Insert($table, $vars){
		$this->query = "INSERT INTO $table SET ";

		$this->vars = array();
		foreach($vars as $key => $value){
			$this->query .= "$key = :$key, ";
			$this->vars[$key] = $value;
		}

		$this->query = substr($this->query, 0, -2);

		return $this->ExecuteSQL($this->query, $this->vars);
	}

// Permet de supprimer une ou des entrée SQL
	public function Delete($table, $where = NULL){
		$this->query = "DELETE FROM $table WHERE ";

		if(!is_array($where)){
			return false;
		}else{
			$this->vars = array();
			foreach($where as $key => $value){
				$this->query .= "$key = :$key AND ";
				$this->vars[$key] = $value;
			}

			$this->query = substr($this->query, 0, -5);

			return $this->ExecuteSQL($this->query, $this->vars);
		}
	}

//Permet de selectionner des données dans la base
	public function Select($table, $value='*', $where = NULL, $param = NULL){
		$this->query = "SELECT $value FROM $table WHERE ";

		if(!isset($param['operand'])){
			$param['operand'] = 'AND';
		}
		if(!isset($param['like'])){
			$param['like'] = false;
		}


		if(is_array($where)){
			foreach($where as $key => $value){

				if($param['like']){
					$this->query .= "$key LIKE %:$key% $param[operand] ";
				}else{
					$this->query .= "$key = :$key $param[operand] ";
				}

				$this->vars[$key] = $value;
			}

			$this->query = substr($this->query, 0, -(strlen($param['operand'])+2));

		}else{
			$this->query = substr($this->query, 0, -6);
		}

		if(isset($param['orderby'])){
			$this->query .= " ORDER BY $param[orderby]";
		}

		if(isset($param['limit'])){
			$this->query .= " LIMIT $param[limit]";
		}
	
		return $this->ExecuteSQL($this->query, $this->vars);
	}

//Permet de mettre à jour des données dans la base
	public function Update($table, $value, $where){
		$this->query = "UPDATE $table SET ";

		foreach($value as $key => $value){
			$this->query .= "$key = :$key, ";
			$this->vars[$key] = $value;
		}
		$this->query = substr($this->query, 0, -2);

		$this->query .= " WHERE ";

		foreach($where as $key=> $value){
			$this->query .= " $key = :$key AND ";
			$this->vars[$key] = $value;
		}

		$this->query = substr($this->query, 0, -5);

		return $this->ExecuteSQL($this->query, $this->vars);
	}



// Retourne le nombre d'entrées
	public function CountRows($table, $where = NULL){
		$param = array('like' => false);
		$result = $this->Select($table,'count(*)',$where,$param);
		return $result["count(*)"];
	}

}