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

Mammouth du PHP | 19672 Messages

09 janv. 2007, 20:35

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 :)
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Mammouth du PHP | 1511 Messages

09 janv. 2007, 23:01

La fonction self::tableau_associatif() c'est un alias de mysql_fetch_assoc ?
@+

Mammouth du PHP | 19672 Messages

09 janv. 2007, 23:19

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.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Mammouth du PHP | 1511 Messages

09 janv. 2007, 23:29

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() ;)
@+

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

10 janv. 2007, 01:43

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 :)

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute

Mammouth du PHP | 19672 Messages

10 janv. 2007, 10:00

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.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

10 janv. 2007, 19:42

Vu comme ça c'est pas faux :)

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute