Poster une réponse  Créer un sujet 
Classe Mysql
Auteur Message
Raoull
Membre


Messages : 442
Groupe : Membre
Inscription : Oct 2006
Statut : Hors ligne
Réputation : 8
Message : #1
Classe Mysql

Une classe Mysql, une de plus, mais qui présente, je crois, quelques nouveautés.

Je me suis inspiré d'une classe assez simple trouvée sur ce site : http://classes.scriptsphp.org/source.mysql

J'ai viré le "ramasse-mettes"/cache, qui réclame une autre classe, et j'ai ajouté 2 choses :

1) Un tableau qui contient toutes les requetes qu'on effectue, leur résultat, insert_id, etc.

2) Un systeme de "requete dynamique" qui n'est en fait qu'une utilisation de sprintf, avec un mysql_real_escape_string sur les chaines, et qui permet de réutiliser une requete en ne faisant varier que les variables.

Cette classe ne contient pas toutes les possibilités de mysql, mais seulement les plus utiles.

Je la teste depuis un moment, et tout fonctionne bien. Mais ce n'est pas une version définitive. J'y travaille sans cesse, corrige les quelques bogues qui surviennent quand je la pousse à fond.
La fonction de debugf est "assez lourde", un simple print_r suffirait sans doute.

Je la mettrai à jour régulièrement.

Mais je vous la présente car elle peut sans doute servir, mais surtout j'aimerai vos remarques et améliorartions possibles.

Utilisation

Cette classe gère donc une unique connexion.
La connexion se fait lors de la première requete à la base, et se ferme lors de la desctrution de l'objet (ou explicitement via la fonction close).

Chaque requete porte un nom (unique ou non), et est stoqué dans le tableau $tabreq par ce nom, qui sera un tableau (2eme dimension) contenant :
- query : la requete sql
- result_id : la ressource résultat
- error : l'erreur mysql_error
- insert_id : le dernier id généré (INSERT)
- dynquery : la requete dynamque
- dynvars : les variables dynamiques

Exemples
A noter pour ces exemple, qu'ils ne sont pas vraiment à suivre en fait car il vaut mieux de pas utiliser les variables $_POST directement dans la requete, mais plustot tester avant si elles sont viables (vides, erreur, etc.) ; mais ce sont de simples exemples...

Exemple 1

Code PHP :
// insertion classe, création de l'objet
include("class.mysql.php");
$bdd = new mysql('server''login''pass''base');

// (optionnel) je me connecte, en spécifiant une autre base
$bdd->connect('autre_base');

// --- une requete simple
$bdd->query('req_1''SELECT id, nom, ville FROM table');

// -- :respect:affiche les résultats dans une boucle, via un mysql_fetch_assoc (par défaut dans get_array())
while($data $bdd->get_array('req_1')) {
    echo 
$data['id'].' . '.data['nom'].' habite à '.data['ville'].'<br />';
}

// (optionnel) on déconnecte
$bdd->close(); 

Exemple 2

Code PHP :
include("class.mysql.php");
$bdd = new mysql('server''login''pass''base');

// --- une requete dynamique simple, d'apres "ville_1" reçu dans un formulaire
$bdd->dynquery(
    
'req_1'// nom de la requete
    
"SELECT id, nom FROM table WHERE ville='%s'"// requete dynamique (format sprintf)
    
$_POST['ville_1'], // une seule variable, on la met direct
    
// on echappe les variables chaines (c notre cas) avec mysql_real_escape_string
);

// -- exploitation résultats
...

// -- on veut faire la meme requete, mais avec une autre ville (ville_2)

// on change uniquement la variable
$bdd->set_dynvars(
    
'req_1'// nom de la requete : le meme
    
$_POST['ville_2'// une seule variable, on la met direct
);

// on réexécute la requete
$bdd->do_dynquery(
    
'req_1'// nom de la requete
    
// on echappe la variable puisque chaine (surtout d'un formulaire)
);

// -- exploitation resultats
...

// -- nb de requete dans le tableau (ici 1 seule)
echo 'On a utilisé '.$bdd->nb_req().' requète(s) différente(s)<br />';

// -- nb de requete exécutées (ici 2)
echo 'On a exécuté '.$bdd->$nb_req_sql.' requète(s)<br />';

// -- déboguage de la requete : affiche toutes les infos et l'éventuelle erreur sur cette requete
echo $bdd->debug('req_1').'<br />;

// -- affiche l'
éventuelle erreur dnas une requete
// généralement mysql_error()
echo $bdd->get_error('req_1');

// -- affiche l'éventuelle erreur générale dans la classe
// par exemple exécution d'une requete qui n'existe pas, etc.
echo $bdd->get_error(); 

Exemple 3

Code PHP :
// --- requète dynamique avec plusieurs variables
$bdd->dynquery(
    
'req_1'// nom de la requete
    
"SELECT * FROM table WHERE nom='%s' AND age=%d AND ville='%s'"// requete dynamique (format sprintf)
    
array( // pluisieurs variables, on utilise un tableau
        
trim($_POST['nom']),
        
intval($_POST['age']),
        
trim($_POST['ville']),
    ),
    
// on echappe les variables chaines
); 

Pour déboguer toutes les requètes envoyées au serveur, et traquer les doublons :

Code PHP :
echo '<pre>';
print_r($bdd->tabreqdebug);
echo 
'</pre>'


Je ne mets pas d'exemple pour toutes les fonctions de la classe, je pense qu'elles sont suffisement explicites et commentées.

La classe

Code PHP :
/*************************************************
Projet    : -
Fichier    : class.mysql.php
Version : 0.8 (jeudi 8 mars 2007)
**************************************************/

class Mysql {

    
/*************************************************
    variables
    **************************************************/

    // identifiant de la connexion
    
private $connect_id 0

    
// tableau des requètes
    
private $tabreq NULL;

    
// erreur générale
    
private $error '';

    
// nb de requètes effectuées à la base SQL
    
public $nb_req_sql 0;

    public 
$tabreqdebug = array();


    
// ********** CONSTRUCTEUR / DESTRUCTEUR ****************************************


    /*************************************************
    Constructeur
    **************************************************
    host : adresse du serveur sql
    user : login
    pass : mot de passe
    base : base à sélectionner
    **************************************************/
    
public function __construct($host 'localhost'$user 'root'$pass ''$base '') {
        
$this->host $host;
        
$this->user $user;
        
$this->pass $pass;
        
$this->base $base;

        
$this->tabreq = array();
    }

    
/*************************************************
    Destructeur
    ferme la connexion (si besoin) et détruit le tableau de requète
    - mysql_close
    - musql_free_result
    **************************************************/
    
function __destruct() {
        
// libère la mémoire de toutes les requètes
        
$ret $this->del_allquery();

        
// ferme la connexion (si besoin)
        
$this->close();

        
// supprime le tableau de requete
        
unset($tabreq);

    }


    
// ********** GESTION DES ERREURS ****************************************


    /*************************************************
    PBLIC get_error : renvoie la dernière erreur générale
            ou la dernière erreur d'une requète
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function get_error($reqid 'default') {
        if (
$reqid == '') {
            
// retourne la dernière erreur de la classe
            
return $this->error;
        }
        else {
            
// retourne la dernière erreur associée à une requete du tableau
            
if (isset($this->tabreq[$reqid]['error'])) {
                return 
$this->tabreq[$reqid]['error'];
            }
            else {
                
// erreur : la requete n'existe pas
                
return FALSE;
            }
        }
    }


    
// ********** CONNEXION / DÉCONNEXION SQL ****************************************


    /*************************************************
    PUBLIC is_connect : Renvoie l'état de la connexion
    connecté = TRUE, non connecté = FALSE
    **************************************************/
    
public function is_connect() {
        if (
$this->connect_id) { return TRUE; }
        else { return 
FALSE; }
    }
    

    
/*************************************************
    PUBLIC : connexion explicite, choix de la base
    - mysql_connect
    - mysql_select_db
    **************************************************
    base : nouvelle base à sélectionner (autre que celle précisé
            lors de la cération de l'objet
    **************************************************/
    
public function connect($base '') {
        
// changement de la base de données
        
if ($base != '') {
            
$this->base->$base;
        }

        if (!
$this->connect_id) {
            
// connexion
            
$connect = @mysql_connect($this->host$this->user$this->pass);
            if (
$connect) {
                if (@
mysql_select_db($this->base$connect)) {
                    
$this->connect_id $connect;
                    return 
TRUE;
                }
                else {
                    
// erreur de la selection de la bdd
                    
die('Connexion impossible à la base de données : '.mysql_error());
                    return 
FALSE;
                }
            }
            else {
                
// erreur lors de la connexion à la bdd
                
die('Connexion impossible à la base de données : '.mysql_error());
                return 
FALSE;
            }
        }
        else {
            
// déjà connecté
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : ferme la connection
    (fait automatiquement dans le destructeur)
    - mysql_close
    **************************************************/
    
public function close() {
        if (
$this->connect_id) {
            
// on déconnecte
            
if (mysql_close($this->connect_id)) {
                
$this->connect_id 0;
                return 
TRUE;
            }
            else {
                
// erreur lors de la déconnexion
                
return FALSE;
            }
        }
        else {
            
// on était pas connecté
            
return TRUE;
        }
    }


    
// ********** GESTION DES REQUETES DYNAMIQUES(DANS LE TABLEAU DE REQUETE) ***********************


    /*************************************************
    PUBLIC : exécute une requete dynamique
    **************************************************
    reqid : nom de la requete
    dquery : requete sql au fomat sprintf
    dvars : expression (1 seule var) ou array, contenant la(es)
            variable(s) à inserer dans la requète
    eescape_string : (0/1) effetue un mysql_real_escape_string sur 
            les variables qui sont des chaines
    **************************************************/
    
public function dynquery($reqid 'default'$dquery ''$dvars NULL$escape_string 0) {
        
        
// stocke la requete dynamique
        
$this->set_dynquery($reqid$dquery);

        
// stocke les variables dynamiques
        
$ret $this->set_dynvars($reqid$dvars);
        if (
$ret === TRUE) {
    
            
// exécute la requete dynamqiue
            
return $this->do_dynquery($reqid$escape_string);
        }
        else {
            
// erreur dans le stockage des variables
            
return $ret;
        }
    }


    
/*************************************************
    PUBLIC : stocke une requete dynamique dans une requete du tableau (sans l'exécuter)
    si la requete n'existe pas dans le tableau, elle est créée
    **************************************************
    reqid : nom de la requete
    dquery : requete sql au fomat sprintf
    **************************************************/
    
public function set_dynquery($reqid 'default'$dquery '') {
        if (isset(
$this->tabreq[$reqid])) { // si requete existe bien

            // stocke la nouvelle requete dynamique
            
$this->tabreq[$reqid]['dynquery'] = $dquery;

            return 
1;
        }
        else { 
// la requete n'existe pas dans le tableau ... on la créé

            // créé une nouvelle requete
            
$this->tabreq[$reqid] = array();

            
// initialise la nouvelle requete
            
$this->tabreq[$reqid]['query'] = '';
            
$this->tabreq[$reqid]['dynquery'] = $dquery;
            
$this->tabreq[$reqid]['dynvars'] = array();
            
$this->tabreq[$reqid]['error'] = '';

            return 
2;
        }
    }

    
/*************************************************
    PUBLIC : stocke les variables dynamique dans une requete du tableau (sans l'exécuter)
    la requete doit exister dans le tableau, et sa requete dynamique aussi !
    **************************************************
    reqid : nom de la requete
    dvars : expression (1 seule var) ou array, contenant le(s)
            variable(s) à inserer dans la requète
    **************************************************/
    
public function set_dynvars($reqid 'default'$dvars NULL) {
        if (!
is_null($dvars)) {
            if (isset(
$this->tabreq[$reqid])) {

                if (isset(
$this->tabreq[$reqid]['dynquery'])) {

                    
// (ré)initialise le tableau des vars dynamques
                    
$this->tabreq[$reqid]['dynvars'] = array();

                    
// on passe les variables au tableau
                    
if (is_array($dvars)) {
                        
// c'est un tableau
                        
$this->tabreq[$reqid]['dynvars'] = $dvars;
                    }
                    else {
                        
// pas 1 tableau : 1 seule var
                        
$this->tabreq[$reqid]['dynvars'][0] = $dvars;
                    }

                    return 
TRUE;
                }
                else { 
// la requete dynamique n'existe pas...
                    
return -3;
                }
            }
            else { 
// la requete n'existe pas...
                
return -2;
            }
        }
        else {
            
// erreur $dvars n'a pas été fourni...
            
return -1;
        }
    }

    
/*************************************************
    PUBLIC : renvoie le nombre de variable dynamique
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function num_dynvars($reqid 'default') {
        if (isset(
$this->tabreq[$reqid]['dynvars'])) {
            return 
count($this->tabreq[$reqid]['dynvars']);
        }
        else {
            return -
1;
        }
    }


    
/*************************************************
    PUBLIC : Exécute une requete dynamique, en option echappe les chaines avec mysql_real_escape_string
    - mysql_query
    **************************************************
    reqid : nom de la requete
    eescape_string : (0/1) effetue un mysql_real_escape_string sur 
            les variables qui sont des chaines
    **************************************************/
    
public function do_dynquery($reqid 'default'$escape_string 0) {

        
// vérifie l'existence de la requete dynamqiue
        
if (isset($this->tabreq[$reqid]['dynquery'])) { // ok, requete existe

            
if ($escape_string == 1) {
                
// échappe les chaines de caratères

                // on se connecte au besoin
                
if (!$this->connect_id) { $this->connect(); }

                for (
$i=0$i<count($this->tabreq[$reqid]['dynvars']); $i++) {
                    
$arg $this->tabreq[$reqid]['dynvars'][$i];
                    if (
is_string($arg)) {
                        
$this->tabreq[$reqid]['dynvars'][$i] = mysql_real_escape_string($arg);
                    }
                }
            }

            
// éxécute les variables dynamqiues
            
$query vsprintf($this->tabreq[$reqid]['dynquery'], $this->tabreq[$reqid]['dynvars']);

            
// stocke la requete finale
            
$this->tabreq[$reqid]['query'] = $query;

            
// on execute la requete
            
$ret $this->do_query($reqid);
            return 
$ret;

        }
        else {
            
// requete n'existe pas
                
$this->tabreq[$reqid]['error'] = 'la requète "'.$reqid.'" n\'existe pas...';
                return 
FALSE;            
        }
    }


    
// ********** GESTION DES REQUETES (DANS LE TABLEAU DE REQUETE) ***********************


    /*************************************************
    PUBLIC : stocke une nouvelle requete (sans l'exécuter)
    **************************************************
    reqid : nom de la requete
    query : requete sql au fomat sprintf
    **************************************************/
    
public function set_query($reqid 'default'$query '') {

        
// supprime la requete si elle existe deja
        
if (isset($this->tabreq[$reqid])) {
            
$this->del_query($reqid);
            
$ret 2;
        }
        else { 
$ret 1; }

        
// créé une nouvelle requete
        
$this->tabreq[$reqid] = array();

        
// initialise la nouvelle requete
        
$this->tabreq[$reqid]['query'] = $query;
        
$this->tabreq[$reqid]['error'] = '';

        return 
TRUE;
    }


    
/*************************************************
    PUBLIC : Supprime une requete du tableau de requete
    - mysql_free_result
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function del_query($reqid 'default') {
        
// si la requete existe on la vire
        
if (isset($this->tabreq[$reqid])) {
            if (isset(
$this->tabreq[$reqid]['result_id'])) {
                @
mysql_free_result($this->tabreq[$reqid]['result_id']);
            }
            unset(
$this->tabreq[$reqid]);
            return 
TRUE;
        }
        else {
            return 
FALSE;
        }
    }


    
/*************************************************
    PUBLIC : Supprime toutes les requetes du tableau de requete
    - mysql_free_result
    (fait automatiquement dans le destructeur)
    **************************************************/
    
public function del_allquery() {
        
$ret 0;
        foreach(
$this->tabreq as $key => $value) {
            if (isset(
$this->tabreq[$key]['result_id'])) {
                @
mysql_free_result($this->tabreq[$key]['result_id']);
                unset(
$this->tabreq[$key]);
                
$ret++;
            }
        }
        return 
$ret;
    }


    
// ********** EXÉCUTION DES REQUÈTES *******************************************


    /*************************************************
    PUBLIC : Créé et exécute une requete
    - mysql_query
    - mysql_insert_id (si INSERT)
    **************************************************
    reqid : nom de la requete
    query : requete sql
    **************************************************/
    
public function query($reqid 'default'$query '') {

        
// on se connecte au besoin
        
if (!$this->connect_id) { $this->connect(); }

        
// créé une nouvelle requète (supprime donc l'ancienne au besoin)
        
$this->tabreq[$reqid] = array();

        
// initialise la nouvelle requète
        
$this->tabreq[$reqid]['query'] = $query;
        
$this->tabreq[$reqid]['error'] = '';

        
// on lance la requete et stocke le résultat
        
if ($this->tabreq[$reqid]['result_id'] = mysql_query($query$this->connect_id) ) {

            
$this->nb_req_sql++;
            
$this->tabreqdebug[$reqid][] = $query;

            
// -- tente de stocker mysql_insert_id si la requete est un INSERT
            
if (preg_match('`^insert`i'$this->tabreq[$reqid]['query'])) {
                
$this->tabreq[$reqid]['insert_id'] = mysql_insert_id();
            }
            
            return 
$this->tabreq[$reqid]['result_id'];
        }
        else {
            
// erreur, on la stocke dans 'error'
            
$this->tabreq[$reqid]['error'] = mysql_error();
            return 
FALSE;
        }
    }


    
/*************************************************
    PUBLIC : Ré-exécute une requete a la DB
    - mysql_query
    - mysql_insert_id (si INSERT)
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function do_query($reqid 'default') {

        
// vérifie l'existence de la requete
        
if (isset($this->tabreq[$reqid]['query'])) { // ok, requete existe

            // on se connecte si besoin
            
if (!$this->connect_id) { $this->connect(); }

            
// réinitialise le tableau pour la requete
            
$this->tabreq[$reqid]['error'] = '';
            if (isset(
$this->tabreq[$reqid]['insert_id'])) {
                unset(
$this->tabreq[$reqid]['insert_id']);
            }
            if (isset(
$this->tabreq[$reqid]['result_id'])) { // optionnel... ?
                //@mysql_free_result($this->tabreq[$reqid]['result_id']);
                
unset($this->tabreq[$reqid]['result_id']);
            }

            
// on lance la requete et stocke le résultat
            
if ($this->tabreq[$reqid]['result_id'] = mysql_query($this->tabreq[$reqid]['query'], $this->connect_id) ) {

                
$this->nb_req_sql++;
                
$this->tabreqdebug[$reqid][] = $this->tabreq[$reqid]['query'];

                
// -- tente de stocker mysql_insert_id si la requete est un INSERT
                
if (preg_match('`^insert`i'$this->tabreq[$reqid]['query'])) {
                    
$this->tabreq[$reqid]['insert_id'] = mysql_insert_id();
                }

                return 
$this->tabreq[$reqid]['result_id'];
            }
            else {
                
// erreur, on la stocke dans 'error'
                
$this->tabreq[$reqid]['error'] = mysql_error();
                return 
FALSE;
            }
        }
        else {
            
// requete n'existe pas
                
$this->tabreq[$reqid]['error'] = 'la requète "'.$reqid.'" n\'existe pas...';
                return 
FALSE;            
        }
    }


    
// ********** GESTION DES RÉSULTATS *******************************************


    /*************************************************
    PUBLIC : renvoie le contenu d'un champ depuis un résultat SQL
    - mysql_result
    **************************************************
    reqid : nom de la requete
    rows : numero de la ligne
    field : nom du champs
    **************************************************/
    
public function get_result($reqid 'default'$rows 0$field '') {
        if (isset(
$this->tabreq[$reqid]['result_id'])) {
            if (
$field == '') {
                return @
mysql_result($this->tabreq[$reqid]['result_id'], $row);
            }
            else {
                return @
mysql_result($this->tabreq[$reqid]['result_id'], $row$field);
            }
        }
        else {
            
// pas de résultat trouvé (et/ou requete inexistante)
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : renvoie un tableau qui contient la ligne demandée depuis un résultat SQL
    - mysql_fetch_object
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function get_object($reqid 'default') {
        if (isset(
$this->tabreq[$reqid]['result_id'])) {
            return @
mysql_fetch_object($this->tabreq[$reqid]['result_id']);
        }
        else {
            
// pas de résultat trouvé (et/ou requete inexistante)
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : renvoie un tableau depuis un résultat SQL
    - mysql_fetch_array
    - mysql_fetch_assoc
    **************************************************
    reqid : nom de la requete
    mode : type de tableau renvoyé :
            - ASSOC (défault) : tableau associatif
            - NUM : tableau numérique
            - BOTH : les deux
    **************************************************/
    
public function get_array($reqid 'default'$mode 'ASSOC') {
        if (isset(
$this->tabreq[$reqid]['result_id'])) {
            switch(
$mode) {
                case 
'NUM' // tableau numérique
                    
return @mysql_fetch_array($this->tabreq[$reqid]['result_id'], MYSQL_NUM);
                    break;
                case 
'BOTH' // tableau numérique ET tableau associatif
                    
return @mysql_fetch_array($this->tabreq[$reqid]['result_id'], MYSQL_BOTH);
                    break;
                case 
'ASSOC' // tableau associatif
                
default :
                    return @
mysql_fetch_assoc($this->tabreq[$reqid]['result_id']);
            }
        }
        else {
            
// pas de résultat trouvé (et/ou requete inexistante)
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : renvoie le nombre d'enregistrement affecté depuis un résultat SQL
    - mysql_num_rows : select
    - mysql_affected_rows : insert, update, replace, delete
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function num_rows($reqid 'default') {
        if (isset(
$this->tabreq[$reqid]['result_id']) && $this->tabreq[$reqid]['result_id']) {
            if (
preg_match('`^select`i'$this->tabreq[$reqid]['query'])) {
                
// après un SELECT
                
return mysql_num_rows($this->tabreq[$reqid]['result_id']);
            }
            elseif (
preg_match('`^(insert|update|replace|delete)`i'$this->tabreq[$reqid]['query'])) {
                
// après un INSERT / UPDATE / REPLACE / DELETE
                
return mysql_affected_rows($this->connect_id);
            }
        }
        else {
            
// pas de résultat trouvé (et/ou requete inexistante)
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : renvoie l'id (auto-increment) généré par une requète, si INSERT
    - mysql_insert_id
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function insert_id($reqid 'default') {
        if (isset(
$this->tabreq[$reqid]['insert_id'])) {
            return 
$this->tabreq[$reqid]['insert_id'];
        }
        else {
            
// pas de résultat trouvé (et/ou insert_id inexistant)
            
return FALSE;
        }
    }


    
/*************************************************
    PUBLIC : renvoie toutes les infos sur une requète, à des fins de déboguage
    **************************************************
    reqid : nom de la requete
    **************************************************/
    
public function debug($reqid 'default') {
        
$debug '';
        if (isset(
$this->tabreq[$reqid])) {
            
$debug .= '<br /><span style="color:#FF0000"><strong>DEBUG Mysql :</strong></span> '.$reqid.'<br /><br />';
            
// query
            
if (isset($this->tabreq[$reqid]['query'])) {
                
$debug .= 'Requète : '.$this->tabreq[$reqid]['query'].'<br /><br />';
            }