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 :

Requête de filtrage


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 718
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 718
    Par défaut Requête de filtrage
    Bonjour,
    J'ai un formulaire qui permet à l'utilisateur d'entrer ses critères de filtrage pour afficher un tableau d'adresses.
    Je crée une requête préparée avec une clause where construite en fonction des critères du formulaire. Je n'ai encore pas tout vérifié mais la dernière clause avec le IN (ligne 37) ne fonctionne pas comme je voudrais. Pour info, $toFilter['groups'] provient d'une liste select à sélection multiple.
    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
    function getFilteredAddresses(int $userId, string $language, array $toFilter): false|array
    {
    	$db = dbConnect();
    	$wheres		= [];
    	$params	= [':id_user'=>$userId];
     
    	if( ! empty($toFilter['from']) )
    	{
    		$wheres[]			= "m.familyname>:from";
    		$params[':from']	= $toFilter['from'];
    	}
     
    	if( !empty($toFilter['to']) )
    	{
    		$wheres[] 			= "m.familyname<:to";
    		$params[':to']		= $toFilter['to'];
    	}
     
    	if( !empty($toFilter['country']) )
    	{
    		$wheres[] 			= "country=:country";
    		$params[':country']	= $toFilter['country'];
    	}
     
    	if( !empty($toFilter['zipcode']) )
    	{
    		$wheres[] 			= "a.zipcode=:zipcode";
    		$params[':zipcode']	= $toFilter['zipcode'];
    	}
     
    	if( !empty($toFilter['locality']) )
    	{
    		$wheres[] 			= "a.locality=:locality";
    		$params[':locality']= $toFilter['locality'];
    	}
     
    	if( !empty($toFilter['groups']) )
    	{
    		$in = implode(',', $toFilter['groups']);
    		$wheres[]			= "g.id_group IN ($in)";
    		/*
    		$in = implode(',', $toFilter['groups']);
    		$wheres[]			= "g.id_group IN (:in)";
    		$params[':in']		= $in;
    		*/
    	}
     
    	var_dump($wheres);
    	var_dump($params);
    	$clause = implode(' AND ', $wheres);
    	if($clause)
    		$clause = " AND " . $clause;
     
    	$sql = <<<SQL
    SELECT DISTINCT a.id, m.familyname, m.firstname, %s_name AS country, a.zipcode, a.locality, m.email, a.homephone, m.GSM
    FROM dat_addresses a
    	LEFT JOIN lst_countries c
    		ON a.country=c.id
    	LEFT JOIN dat_members m
    		ON a.id=m.id_address
    	LEFT JOIN dat_groups g
    		ON a.id=g.id_address
    WHERE id_user=:id_user AND m.relation=0%s
    ORDER BY m.familyname, m.firstname
    SQL;
    	$sql = sprintf($sql, $language, $clause);
    	$stmt = $db->prepare($sql);
    	$stmt->execute($params);
    	return $stmt->fetchAll();
    }
    Le code de la ligne 40 n'est pas paramétré et me donne le résultat attendu avec deux adresses mais le code en commentaire est paramétré mais ne donne qu'une adresse.
    En version non paramétrée, la ligne 48 donne:
    array (size=2)
      0 => string 'country=:country' (length=16)
      1 => string 'g.id_group IN (1,2,3)' (length=21)
    
    et la ligne 49:
    array (size=2)
      ':id_user' => int 2
      ':country' => string 'FR' (length=2)
    
    En version paramétrée, la ligne 48 donne:
    array (size=2)
      0 => string 'country=:country' (length=16)
      1 => string 'g.id_group IN (:in)' (length=19)
    
    et la ligne 49:
    array (size=3)
      ':id_user' => int 2
      ':country' => string 'FR' (length=2)
      ':in' => string '1,2,3' (length=5)
    Question: Est-ce qu'il y aurait un inconvénient à ne pas paramétrer cette clause qui ne contient que des valeurs numériques?
    Sinon, comment faire pour avoir le bon résultat?

  2. #2
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    La seule chose que tu puisses passer en paramètre à une requête préparée est une valeur, mais en aucun cas tu ne peux passer en paramêtre un "morceau de requête" comme plusieurs valeurs séparées par des virgules.
    Si tu es sûr de ton fait, c'est à dire si tu as vérifié coté serveur que toutes tes valeurs sont bien de type int, alors oui, rien ne t'empêche de faire ton implode puis d'insérer ça directement dans la requête. Autre solution, au lieu d'utiliser des placeholders nommés, tu peux utiliser des jokers ? et composer ta requête en fonction du nombre de valeurs: j'ai trois valeurs donc la requête sera in (?,?,?). Le seul problème avec les jokers, c'est qu'il faut bien veiller à ce que les paramètres de la requête soient fournis dans l'ordre d'apparition des dits jokers.

  3. #3
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Bonjour,

    En complément de la réponse précédente.

    Ici les groupes sont copiés,
    puis itérés pour générer des noms de paramètres,
    au passage,
    le tableau des valeurs des paramètres est mis à jour.

    Le reste est similaire à votre tentative.

    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
    <?php
    $toFilter=[];
    $toFilter['groups']= [1,2,3];
    $wheres=[];
    $params=[];
     
    if( !empty($toFilter['groups']) )
    {
    	$in = $toFilter['groups'];
    	foreach($in as $k=>$v) {
    		$in[$k]=":group_$k";
    		$params[":group_$k"]=$v;
    	}
    	$in = implode(',', $in);
    	$wheres[] = "g.id_group IN ($in)";
    }
     
    var_dump($toFilter);
    var_dump($wheres);
    var_dump($params);
    Affichera

    Code php : 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
    array(1) {
      ["groups"]=>
      array(3) {
        [0]=>
        int(1)
        [1]=>
        int(2)
        [2]=>
        int(3)
      }
    }
    array(1) {
      [0]=>
      string(42) "g.id_group IN (:group_0,:group_1,:group_2)"
    }
    array(3) {
      [":group_0"]=>
      int(1)
      [":group_1"]=>
      int(2)
      [":group_2"]=>
      int(3)
    }

    En PHP la copie des tableaux est automatique, et, superficielle,
    https://www.php.net/manual/fr/langua...les.basics.php
    Les variables sont toujours assignées par valeur. C'est-à-dire, lorsque vous assignez une expression à une variable, la valeur de l'expression est recopiée dans la variable. Cela signifie, par exemple, qu'après avoir assigné la valeur d'une variable à une autre, modifier l'une des variables n'aura pas d'effet sur l'autre.
    Éventuellement il y a le cas des références et des objets,
    mais ce n'est pas le sujet ici.

    Autrement, pour plus de clarté,
    vous pourriez mettre ce %s à la ligne,
    voir, simplement utiliser le mécanisme d'interprétation des variables.
    https://www.php.net/manual/fr/langua...string.parsing


    Bonne journée.

  4. #4
    Membre éprouvé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 718
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 718
    Par défaut
    Merci à vous deux. Effectivement mes valeurs sont bien des int. Je vais donc garder la solution qui marche.

  5. #5
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    J'insiste sur le fait que les int doivent être vérifiés coté serveur (donc en PHP), car les contraintes de formulaires coté client ne constituent pas une garantie (elles sont plus un confort pour l'utilisateur).

  6. #6
    Membre chevronné
    Homme Profil pro
    Urbaniste
    Inscrit en
    Août 2023
    Messages
    387
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Autre

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Août 2023
    Messages : 387
    Par défaut
    Citation Envoyé par moimp Voir le message
    Merci à vous deux. Effectivement mes valeurs sont bien des int. Je vais donc garder la solution qui marche.
    Bonjour,

    si la solution prend ses jambes à son cou, faites nous signe.

    Bonne journée.

  7. #7
    Membre éprouvé
    Homme Profil pro
    Ingénieur en électrotechnique retraité
    Inscrit en
    Décembre 2008
    Messages
    1 718
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Ingénieur en électrotechnique retraité

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1 718
    Par défaut
    Merci de me mettre en garde. La balise select du formulaire est construite à partir d'une table en bdd qui ne contient que des valeurs entières, lesquelles sont comparées à d'autres valeurs entières d'une autre table ce qui signifie que toute autre valeur ne fonctionnerait pas. D'autre part en insertion dans les deux tables le type entier des valeurs est contrôlé en php et déclaré int dans les tables.

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

Discussions similaires

  1. filtrage d'une table interbase
    Par kouraichi35 dans le forum Bases de données
    Réponses: 4
    Dernier message: 04/11/2004, 13h08
  2. filtrage d'une chaine de caractéres
    Par localhost dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 20/09/2003, 01h11
  3. petit probleme dans une requte POSTGRE SQL
    Par ghis le fou dans le forum Requêtes
    Réponses: 5
    Dernier message: 08/09/2003, 13h51
  4. Problèmes avec le filtrage des ip
    Par berry dans le forum Réseau
    Réponses: 9
    Dernier message: 30/12/2002, 07h51
  5. Matrice de filtrage ?
    Par gimlithedwarf dans le forum Traitement d'images
    Réponses: 2
    Dernier message: 24/08/2002, 09h44

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