IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

PHP & Base de données Discussion :

PDO select et conditions multiples sur la même colonne [PDO]


Sujet :

PHP & Base de données

  1. #1
    Membre actif Avatar de greg91
    Homme Profil pro
    Administrateur système
    Inscrit en
    Novembre 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur système

    Informations forums :
    Inscription : Novembre 2007
    Messages : 121
    Points : 208
    Points
    208
    Par défaut PDO select et conditions multiples sur la même colonne
    Bonjour,

    J’essaie de faire une requête préparée comme ça :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SELECT COUNT(idDimmoAds) FROM 
        `dimmoAds` 
    WHERE 
        `dimmoAds`.`typeAds` = :typeAds 
    AND 
        `dimmoAds`.`typeProperty` != :typeProperty 
    AND 
        `dimmoAds`.`typeProperty` != :typeProperty 
    AND 
        `dimmoAds`.`typeProperty` != :typeProperty 
    AND 
        `dimmoAds`.`typeProperty` != :typeProperty

    Voici le code php qui me permet de "bindder" mes paramètres :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    if (!empty($selectOption)) {
        foreach ($selectOption as $key => $options) {
            echo 'Valeur'.'->'.$options['value'];
            $stmt->bindValue(":$options[field]", $options['value']);
        }
    }
    Le "echo 'Valeur'.'->'.$options['value'];" m'affiche bien les bonnes valeurs :
    - Valeur->Location
    - Valeur->Immeuble
    - Valeur->Maison
    - Valeur->Terrain
    - Valeur->Parking

    Mais le log MySql me dit que c'est cette requête qui est passée :

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT
        COUNT(idDimmoAds)
    FROM
        `dimmoAds`
    WHERE 
        `dimmoAds`.`typeAds` = 'Vente' 
    AND `dimmoAds`.`typeProperty` != 'Parking' 
    AND `dimmoAds`.`typeProperty` != 'Parking' 
    AND `dimmoAds`.`typeProperty` != 'Parking' 
    AND `dimmoAds`.`typeProperty` != 'Parking'

    Je n'ai pas du tout comprendre aux requêtes préparées moi

    Quelqu'un peut m'aider ?

  2. #2
    Modérateur
    Avatar de sabotage
    Homme Profil pro
    Inscrit en
    Juillet 2005
    Messages
    29 208
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations forums :
    Inscription : Juillet 2005
    Messages : 29 208
    Points : 44 155
    Points
    44 155
    Par défaut
    Tu ne peux pas avoir plusieurs fois le même nom de paramètre.

    Tu peux composer ta requête automatiquement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    $sql = 'SELECT COUNT(idDimmoAds) FROM 
        `dimmoAds` 
    WHERE 
        `dimmoAds`.`typeAds` = :typeAds'
     
    $param[] = $typeAds
     
    if (!empty($selectOption)) {
                foreach ($selectOption as $key => $options) {
                    $sql .= ' AND  `dimmoAds`.`' . $options['field'] . '` !=  ?'
                    $param[] = $options['value'];
                }
            }
    $stmt->execute($param);

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Juillet 2012
    Messages
    200
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations forums :
    Inscription : Juillet 2012
    Messages : 200
    Points : 342
    Points
    342
    Par défaut
    Bonjour à tous!
    Pour optimiser la requête, il serait mieux d'utiliser une liste pour les valeurs que ne doit pas avoir typeProperty.
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT
        COUNT(idDimmoAds)
    FROM
        `dimmoAds`
       WHERE `dimmoAds`.`typeAds` = ? 
    AND 
        `dimmoAds`.`typeProperty` NOT IN (?, ?, ?, ?)
    Cela donnera donnera donc comme code php
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    $query = 'SELECT
        COUNT(idDimmoAds)
    FROM
        `dimmoAds
       WHERE `dimmoAds`.`typeAds` = :typeAds
    AND 
        `dimmoAds`.`typeProperty` NOT IN (:typeProperty1, :typeProperty2, :typeProperty3, :typeProperty4)
    Ensuite tu lies les paramètres et tu exécute ta requête

  4. #4
    Membre actif Avatar de greg91
    Homme Profil pro
    Administrateur système
    Inscrit en
    Novembre 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur système

    Informations forums :
    Inscription : Novembre 2007
    Messages : 121
    Points : 208
    Points
    208
    Par défaut
    Merci beaucoup les gars, c'est vrai que je n'utilise jamais les '?' dans mes requêtes car j'avais jamais vraiment eu à les utiliser (jusqu'à aujourd’hui en tout cas )

    Là, je ne m'en sort pas. Le but de mon code est d'avoir une classe "manager" de table de données qui implémente les méthodes dont on a toujours besoin :
    ajout, listing, lecture, mise à jour, suppression, compter, existence.

    Mais je pense que mon code est finalement contre productif et je dois faire fausse route.

    Je donne ma méthode pour compter les éléments d'une table en fonction de critères. Elle commence à être compliquée et je ne vous en voudrai pas de ne pas prendre le temps

    De toute façon je pense que je fait fausse route.

    Classe Manager :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    class DimmoAdsManager
    {
        /**
         * Compte le nombre d'enregistrement.
         *
         * @param array  $selectOption Conditions pour la requête SQL.
         *                             Format : [TABLE][CHAMP][OPERATEUR (=,<,>...)][VALEUR]
         *
         * @return int Nombre d'enregistrement
         */
        public static function count($selectOption)
        {
            $connexion_db = PDO2::getInstance();
     
            /* Construction de la requête SQL en fonction des paramètres */
            $sql = "
                SELECT
                    COUNT(idDimmoAds)
                FROM
                    `dimmoAds`
            ";
     
            if (!empty($selectOption)) {
                //Critères de sélection dans $selectOption
                $nbeSelectOption = count($selectOption);
     
                if ($nbeSelectOption === 1) {
                    //Une seule option
                    foreach ($selectOption as $key => $options) {
                        $sql .= "WHERE `$options[table]`.`$options[field]` $options[operator] :$options[field] ";
                    }
                }
     
                if ($nbeSelectOption > 1) {
                    //Plusieurs options
                    $pointer = 1;
                    foreach ($selectOption as $key => $options) {
                        if ($pointer === 1) {
                            //Premier passage de la boucle
                            $sql .= "WHERE `$options[table]`.`$options[field]` $options[operator] :$options[field] ";
                        }
                        if ($pointer != 1) {
                            $sql .= "AND `$options[table]`.`$options[field]` $options[operator] :$options[field] ";
                        }
                        $pointer++;
                    }
                }
            }
     
            /* Préparation de la requête */
            $stmt = $connexion_db->prepare($sql);
     
            /* Protection des variables de la requête */
            if (!empty($selectOption)) {
                foreach ($selectOption as $key => $options) {
                    echo 'Valeur'.'->'.$options['value'];
                    $stmt->bindValue(":$options[field]", $options['value']);
                }
            }
     
            self::_executeRequest($stmt);
            return $stmt->fetchColumn();
        }
    }
    Utilisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    $selectOption = array();
    $selectOption[] = array(
        'table' => 'dimmoAds',
        'field' => 'typeAds',
        'operator' => '=',
        'value'=> 'Vente'
    );
    $selectOption[] = array(
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '!=',
        'value'=> 'Immeuble'
    );
    $selectOption[] = array(
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '!=',
        'value'=> 'Maison'
    );
    $selectOption[] = array(
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '!=',
        'value'=> 'Terrain'
    );
    $selectOption[] = array(
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '!=',
        'value'=> 'Parking'
    );
     
    $_dimmoNbeAdsSaleOther = DimmoAdsManager::count($selectOption);
    Ya sûrement mieux à faire que de passer des paramètres en tableaux.
    Au final ça deviens plus clair de créer la requête dans le modèle et le l'envoyer à la classe ensuite...
    Je sais plus

  5. #5
    Expert éminent sénior
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Dev indep

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 142
    Points : 16 545
    Points
    16 545
    Billets dans le blog
    12
    Par défaut
    Salut,

    je t'ai repris le code de ta classe afin de le simplifier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    class DimmoAdsManager
    {
        /**
         * Compte le nombre d'enregistrement.
         *
         * @param array  $selectOption Conditions pour la requête SQL.
         *                             Format : [TABLE][CHAMP][OPERATEUR (=,<,>...)][VALEUR]
         *
         * @return int Nombre d'enregistrement
         */
        public static function count(array $selectOption)
        {
            // suit les tags PDO et leur valeur
            $tags    = array();
            // générateur de tag PDO a->z + A->Z
            $chars   = array_flip(range('a', 'z')) + array_flip(range('A', 'Z'));
            // génère et renvoie un tag (suite aléatoire de 10 lettres)
            $get_tag = function() use ($chars) { return ':'.implode(array_rand($chars, 10)); };
     
            $add_tag =
                function($value) use ($get_tag, &$tags)
                {
                    // on s'assure de l'unicité du tag généré pour l'ensemble de la requête
                    // si le tag a déjà été généré, on en génère autant de fois que nécéssaire pour préserver l'unicité
                    do
                    {
                        $tag = $get_tag();
                    } while (isset($tags[$tag]));
     
                    $tags[$tag] = $value;
     
                    return $tag;
                };
     
            // suit les critères du filtre
            $where = array();
     
            foreach ($selectOption as $k => $options)
            {
                $where[] =
    <<<SQL
    `{$options['table']}`.`{$options['field']}` {$options['operator']} {$add_tag($options['value'])}
    SQL;
            }
     
            $sql_where = (empty($where)) ? '' : ' WHERE '.implode('AND', $where);
            $sql       = "SELECT COUNT(`idDimmoAds`) AS nb_rec FROM `dimmoAds` {$sql_where}";
     
            /* Préparation de la requête */
            $cnx  = PDO2::getInstance();
            $stmt = $cnx->prepare($sql);
     
            /* Protection des variables de la requête */
            foreach ($tags as $tag => $value)
            {
                $stmt->bindValue($tag, $value);
            }
     
            self::_executeRequest($stmt);
            return $stmt->fetchColumn();
        }
    }
    J'ai essayé de coller à ton approche.
    Allez bon courage, je pense que tu vas y passer un peu de temps sur ce bout de code..., désolé
    Si tu pousses l'architecture, toute la partie de la gestion des tags est factorisable.

  6. #6
    Membre actif Avatar de greg91
    Homme Profil pro
    Administrateur système
    Inscrit en
    Novembre 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur système

    Informations forums :
    Inscription : Novembre 2007
    Messages : 121
    Points : 208
    Points
    208
    Par défaut
    Merci beaucoup rawsrc, ton code fonctionne
    Reste qq problèmes avec certains filtres que je vais essayer de régler.

    Je repost si à nouveau je ne m'en sort pas (là c les vacances)

  7. #7
    Membre actif Avatar de greg91
    Homme Profil pro
    Administrateur système
    Inscrit en
    Novembre 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France

    Informations professionnelles :
    Activité : Administrateur système

    Informations forums :
    Inscription : Novembre 2007
    Messages : 121
    Points : 208
    Points
    208
    Par défaut
    Et bien merci encore rawsrc, Ton code marche super !

    Je l'ai adapté vers quelque choses que je comprenais mieux J'ai suivi ton conseil et ai mis la générations des tag dans une méthode privée.
    Je post le code final et m'attaque au listing maintenant.

    La classe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
     
    class DimmoAdsManager
    {
        /**
         * Compte le nombre d'enregistrement.
         *
         * @param array $selectOption Conditions pour la requête SQL.
         *                            [][OPERATEUR_GENERALE][TABLE][CHAMP][OPERATEUR (=,<,>...)][VALEUR]
         *
         * @return int Nombre d'enregistrement répondant aux conditions de sélections
         */
        public static function count(array $selectOption)
        {
            /**
             * Liste des tags PDO et de leur valeur
             * [TAG_ALEATOIRE][VALEUR]
             * @var Array
             */
            $tags = array();
     
            /**
             * Liste des critères SQL du filtre
             * @var Array
             */
            $where = array();
     
            /* Options de selections */
            foreach ($selectOption as $options) {
                //Génère un nouveau tag
                $tag = self::_generateTag($tags);
     
                //Ajoute le tag et sa valeur
                $tags[$tag] = $options['value'];
     
                /* Ajout de l'option de sélection dans la liste des critères */
                $where[] = "
                {$options['masterOperator']}
                `{$options['table']}`.`{$options['field']}`
                {$options['operator']}
                :{$tag}
                ";
            }
     
            /* Contruction de la requête SQL */
            $sql_where = (empty($where)) ? '' : ' WHERE '.implode(' ', $where);
            $sql       = "SELECT COUNT(`idDimmoAds`) AS nb_rec FROM `dimmoAds` {$sql_where}";
     
            /* Préparation de la requête */
            $connexion_db = PDO2::getInstance();
            $stmt = $connexion_db->prepare($sql);
     
            /* Protection des variables de la requête */
            foreach ($tags as $tag => $value) {
                $stmt->bindValue($tag, $value);
            }
     
            if (!$stmt->execute()) {
                if (CORE_DEBUG === true) {
                    //Affiche l'erreur en mode de debug
                    print_r($stmt->errorInfo());
                }
            return $stmt->fetchColumn();
        }
     
        /**
         * Génére un nouveau tag unique en controlant qu'il n'a pas déjà été généré
         *
         * @param array  $tags Liste des tags déjà généré par la requête
         *
         * @return string
         */
        private function _generateTag($tags)
        {
            $chars = array_flip(range('a', 'z')) + array_flip(range('A', 'Z'));
     
            do {
                implode(array_rand($chars, 10));
                $tag = Chaine::random(10, 1);
            }
            while (array_key_exists($tag, $tags));
     
            return $tag;
        }
    }
    Utilisation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    /* Options de sélection */
    $selectOption[] = array(
        'masterOperator' => '',
        'table' => 'dimmoAds',
        'field' => 'typeMandat',
        'operator' => '=',
        'value'=> 'Exclusif'
    );
     
    $selectOption[] = array(
        'masterOperator' => 'AND',
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '=',
        'value'=> 'Maison'
    );
     
    $selectOption[] = array(
        'masterOperator' => 'OR',
        'table' => 'dimmoAds',
        'field' => 'typeProperty',
        'operator' => '=',
        'value' => 'Appartement'
    );
     
    $selectOption[] = array(
        'masterOperator' => 'AND',
        'table' => 'dimmoAds',
        'field' => 'typeAds',
        'operator' => '=',
        'value'=> 'Vente'
    );
     
    $test = DimmoAdsManager::count($selectOption);
    var_dump($test);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/11/2010, 17h19
  2. Requête avec conditions multiples sur le même champ
    Par skerdreux dans le forum Langage SQL
    Réponses: 2
    Dernier message: 25/06/2008, 19h15
  3. Accès multiple sur une même table
    Par ravaid dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 18/04/2008, 14h09
  4. Accès multiple sur une même table
    Par ravaid dans le forum Développement
    Réponses: 3
    Dernier message: 18/04/2008, 13h27
  5. Réponses: 4
    Dernier message: 27/05/2007, 15h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo