Page 1 sur 1

Lister les valeurs d'un champ de type SET ou ENUM

Posté : 09 janv. 2007, 20:35
par Cyrano
Je me suis trouvé face à un problème et l'utilisation d'une procédure stockée m'opposant une farouche résistance, j'ai contourné le problème autrement.

But de la manoeuvre :
Obtenir la liste des valeurs possibles dans un champ de type SET ou ENUM pour construire à la volée une liste déroulante dans un formulaire. Voici comment j'ai procédé.

D'abord utiliser une requête SHOW pour récupérer les informations sur la colonne visée :

Code : Tout sélectionner

SHOW COLUMNS FROM telephone WHERE Field = 'tel_type';
Celle-ci s'exécute sans la moindre anicroche et retourne un tableau comme celui-ci :

Code : Tout sélectionner

mysql> SHOW COLUMNS FROM telephone WHERE Field = 'tel_type'; +----------+--------------------------------------------+------+-----+----------+-------+ | Field | Type | Null | Key | Default | Extra | +----------+--------------------------------------------+------+-----+----------+-------+ | tel_type | enum('domicile','portable','fax','bureau') | NO | | domicile | | +----------+--------------------------------------------+------+-----+----------+-------+ 1 row in set (0.02 sec)
Ensuite, je récupère le résultat et deux colonnes m'intéressent : Type et Default
Je parse ça avec une toute petite expression régulière.

Comme j'utilise une classe perso, vous n'aurez pas le code de connexion ni l'exécution, mais on s'en cogne, ce qui nous intéresse est la suite. Voici la méthode complète avec les commentaires :
<?php
//...
    /**
     * Liste des valeurs possibles.
     *
     * La méthode va récupérer les valeurs possible d'une colonne de
     * type ENUM ou SET.
     * Les valeur seront isolées et stockées dans un tableau. Ce tableau
     * a deux dimensions, la première contient un tableau de valeurs, la
     * seconde une chaine avec la valeur par défaut.
     * Par exemple :
     * <code>$option_telephone = $cnx_rechdetail->listeEnum("telephone", "tel_type");</code>
     * Va retourner un tableau comme celui-ci :
     * <code>array(2) {
     *   ["valeurs"]=>
     *   array(4) {
     *     [0]=>
     *     string(8) "domicile"
     *     [1]=>
     *     string(8) "portable"
     *     [2]=>
     *     string(3) "fax"
     *     [3]=>
     *     string(6) "bureau"
     *   }
     *   ["defaut"]=>
     *   string(8) "domicile"
     * }</code>
     *
     * @param  String $table    Table où se trouve la colonne à consulter
     * @param  String $colonne  Colonne dont on veut les valeurs
     * @return Array
     */
    public function listeEnum($table, $colonne)
    {
        /* Construction de la requête */
        $this->setNouvelleRequete("SHOW COLUMNS FROM ". $table ." WHERE Field = '". $colonne ."';");
        $chaine = "";
        $defaut = "";
        while(false != ($ligne = $this->tableau_associatif()))
        {
            $chaine = $ligne['Type'];
            $defaut = $ligne['Default'];
        }
        /* Traitement de la chaine récupérée */
        $masque = "#(?:enum|set)\('([^\)].*)'\)$#i";
        $valeurs = preg_replace($masque, "$1", $chaine);
        $tval = explode("','", $valeurs);
        $retour = array("valeurs" => $tval, "defaut" => $defaut);
        return $retour;
    }
//...
?>
Voilà, avec ça, on récupéere un tableau qu'il suffit de passer dans une boucle pour construire rapidement des listes déroulantes avec éventuellement une option sélectionnée par défaut.

Enjoy :)

Posté : 09 janv. 2007, 23:01
par momox
La fonction self::tableau_associatif() c'est un alias de mysql_fetch_assoc ?
@+

Posté : 09 janv. 2007, 23:19
par Cyrano
C'est une des fonction de ma propre classe d'accès à MySQL qui utilise effectivement mysqli_fetch_assoc() et me retourne le résultat. Ceci dit, l'idée, c'est que j'ai commencé à mon monter ma propre couche d'abstraction et j'ai donc créé mes propres fonctions qui font appel à des méthodes correspondant à chaque SGBD envisagé. Or ce nom là est suffisamment explicite, ce qui est le but de la manoeuvre.

Mais comme j'ai dit, le code de connexion et de récupération, on s'en tape un peu, chacun à ce stade sait comment récupérer ce type d'information. Et la partie intéressante, c'est l'exploitation de ce résultat dans ce cas précis.

Posté : 09 janv. 2007, 23:29
par momox
Exactement, mais bon, je préfere poser les questions car sur le coup, je me suis dit qu'il y avait ptet un traitement spéchole des données avec ce self::tableau_associatif() ;)
@+

Posté : 10 janv. 2007, 01:43
par Truc
Me semblais bien déjà avoir vu un post en parler

Sinon juste pour chipotter... un if() ne suffirait pas à la place du while() ?
while(false != ($ligne = $this->tableau_associatif()))
On sait qu'il n'y aura qu'un tuple... optimisation optimisation :lol:

Utile :)

Posté : 10 janv. 2007, 10:00
par Cyrano
Non : si tu as plusieurs champs de type ENUM dans la même table, tu pourrais avoir un (ou plusieurs) "OR" dans la requête pour pointer sur chacun de ces champs et tu auras donc plusieurs lignes. Ce qu'il faudrait donc améliorer encore dans ma méthode, c'est le paramètre $colonne qui devrait en fait être un tableau et ensuite construire la clause WHERE dynamiquement.

Posté : 10 janv. 2007, 19:42
par Truc
Vu comme ça c'est pas faux :)