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 préparée qui ne fonctionne pas [MySQL]


Sujet :

PHP & Base de données

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Conseil en assistance à maîtrise d'ouvrage
    Inscrit en
    Juin 2019
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Conseil en assistance à maîtrise d'ouvrage

    Informations forums :
    Inscription : Juin 2019
    Messages : 28
    Par défaut Requête préparée qui ne fonctionne pas
    Bonjour,
    J'ai préparé un formulaire de recherche interrogeant une base qui recense des interviews : une table interviews, une table interviewés et une table d'association.
    Pour le moment j'ai seulement une requête de type LIKE qui interroge un champ de texte de la table interviews, mais je dois ajouter des critères de recherche.
    Ceux-ci prendront la forme de cases à cocher dans le formulaire, ce qui engendre une succession de conditions WHERE que je veux concaténer si le critère est présent dans $_POST.
    (j'espère que cette présentation est claire...)
    J'ai donc voulu préparer ma requête en écrivant "WHERE ?" et en l'exécutant avec dans l'array une variable $criteres qui contient la concaténation desdits critères issus de $_POST.
    Pour le moment, je n'ai mis en place que le critère LIKE... mais ça ne fonctionne déjà pas !
    Je pense que ma syntaxe est mauvaise, sans doute dans la variable $critere peut-être ?

    voici mon code :
    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
     
    <?php
    if(isset($_POST) && $_POST['motscles'] != NULL)
    	{
     
    		// connexion bdd
    		try
    		{
    			$bdd = new PDO('mysql:host=localhost;dbname=base;charset=utf8', 'root', '');
    			$bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    		}
    		catch(Exception $e)
    		{
    		        die('Erreur : '.$e->getMessage());
     
     
    		}
     
    		// on prépare la requête mySQL
    		$reponse = $bdd->prepare("SELECT GROUP_CONCAT( CONCAT(t.civilite, ' ', t.prenom, ' ', t.nom, ', ', t.qualite) ORDER BY t.nom SEPARATOR ' ~~ ') AS groupe, i.id, i.nom_fichier
    					FROM temoins as t
    					INNER JOIN asso_temoins ON t.id = temoin_id
    					INNER JOIN temoignages as i ON i.id = temoignage_id
    					WHERE ?
    					GROUP BY i.id
    					ORDER BY i.nom_fichier");
     
     
    		// on construit le WHERE de la requête en concaténant les critères de recherche présent dans $_POST
     
    		if(isset($_POST['motscles']) && $_POST['motscles'] != NULL)
    			$chaine = htmlspecialchars($_POST['motscles']);
    			$criteres = "i.retranscription LIKE '%$chaine%'";
     
     
     
    		// on exécute le requête et on affiche les résultats
     
    		$reponse->execute(array($criteres));
     
    		if ($reponse->rowCount() == 0) {
    		   echo 'Aucun résultat<br /><a href="recherche.php">Retour au formulaire de recherche</a>';
    		}
    		else{
     
    				?>
     
    				<p>
    					<?php
    					if ($reponse->rowCount() == 1)
    					{echo '1 résultat :';}
    					else {echo $reponse->rowCount(). ' résultats :';}
    					?>
    				</p>
     
    				<?php
     
    				while ($donnees = $reponse->fetch())
    				{
    					?>
    					    <p>
    					    	<a href="temoignage.php?id=<?php echo $donnees['id']?>">
    					    		Témoignage de&nbsp;
    					    		<?php echo $donnees['groupe'];?>
    					    	</a>
    					    </p>
    					<?php
    				}
    			}
     
    			$reponse->closeCursor(); // Termine le traitement de la requête
     
    		}
     
    else
    	{echo '
    	Veuillez taper un mot-clé ou sélectionner au moins un critère de recherche avancée<br />
    	<a href="recherche.php">Retour au formulaire de recherche</a>
    	' ;}
     
    ?>
    Le résultat obtenu est mon " echo 'Aucun résultat ", autrement dit il n'arrive pas à prendre en compte la chaîne de caractères à rechercher

    Je précise que la requête fonctionne lorsqu'elle n'est pas préparée, c'est-à-dire avec ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    $reponse = $bdd->query("SELECT GROUP_CONCAT( CONCAT(t.civilite, ' ', t.prenom, ' ', t.nom, ', ', t.qualite) ORDER BY t.nom SEPARATOR ' ~~ ') AS groupe, i.id, i.nom_fichier
    								FROM temoins as t
    								INNER JOIN asso_temoins ON t.id = temoin_id
    								INNER JOIN temoignages as i ON i.id = temoignage_id
    								WHERE i.retranscription LIKE '%$chaine%'
    								GROUP BY i.id
    								ORDER BY i.nom_fichier");
    Merci beaucoup d'avance pour votre aide !

  2. #2
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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
    Billets dans le blog
    12
    Par défaut
    Salut,

    effectivement tu ne peux pas procéder ainsi car pour que la préparation de la requête fonction il faut obligatoirement qu'elle soit détaillée au moment de la préparation donc il faut qu'elle ait des placeholder dans sa définition.
    Pour cela il faut compiler les valeurs des cases à cocher et leur allouer des :tags
    Poste voir le code source du formulaire, stp.

  3. #3
    Membre averti
    Homme Profil pro
    Conseil en assistance à maîtrise d'ouvrage
    Inscrit en
    Juin 2019
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Conseil en assistance à maîtrise d'ouvrage

    Informations forums :
    Inscription : Juin 2019
    Messages : 28
    Par défaut
    Merci, je m'en doutais un peu mais je suis perdu !
    Voici le code du formulaire: en plus du champ de texte (pour la requête LIKE), les 3 cases à cocher interrogeront trois champs de la table temoignages "audio", "video", "documents" qui bien sûr peuvent avoir pour valeur 0 ou 1

    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
    <form method="post" action="resultats.php">
     
    				<p>
    					<label for="motscles">Saisissez votre recherche</label> : <input type="text" name="motscles" id="motscles" />
    				</p>
     
    				<br />
     
    				<details>
    					<summary>Recherche avancée</summary>
    					<fieldset>
    						<p><em>
    							Tous les témoignages ont une version texte. La plupart ont une version audio et, en fonction de l'accord des témoins, presque tous une vidéo.<br />
    							Vous pouvez ici filtrer la recherche pour afficher seulement les résultats comportant obligatoirement au moins de l'audio / de la vidéo.<br />
    							Vous pouvez également n'afficher que les témoignages où des documents (photos, archives, etc.) sont présentés par les témoins.
    						</em></p>
    						<ul class="liste-cases">
    							<li><input type="checkbox" name="audio" id="audio" /> <label for="audio">Témoignages comportant obligatoirement un fichier audio</label></li>
    							<li><input type="checkbox" name="video" id="video" /> <label for="video">Témoignages comportant obligatoirement un fichier vidéo</label></li>
    							<li><input type="checkbox" name="documents" id="documents" /> <label for="documents">Témoignages dans lesquels des documents sont présentés</label></li>
    						</ul>
    					</fieldset>
    				</details>
     
    				<br />
     
    				<input type="submit" value="Valider" />
     
    			</form>

  4. #4
    Expert confirmé
    Avatar de rawsrc
    Homme Profil pro
    Dev indep
    Inscrit en
    Mars 2004
    Messages
    6 142
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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
    Billets dans le blog
    12
    Par défaut
    c'est un poil plus compliqué que tu ne te l'imagine :
    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
    85
    86
    87
    88
    89
    90
    91
    <?php
     
    // interception d'absence de mots clés
    if (empty($_POST['motscles'])) {
        echo <<<'html'
    Veuillez taper un mot-clé ou sélectionner au moins un critère de recherche avancée<br />
    <a href="recherche.php">Retour au formulaire de recherche</a>
    html;
        exit;
    }
     
    // traitement de la recherche
    // connexion bdd
    try {
        $pdo = new PDO('mysql:host=localhost;dbname=base;charset=utf8', 'root', '', [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES   => false
        ]);
    } catch(Exception $e) {
        die('Erreur : '.$e->getMessage());
    }
     
    $where = [];
    $data  = [];
    $type  = [];    // types de données pour PDO
     
    // construction de la clause WHERE
    $data[':motscles'] = '%'.$_POST['motscles'].'%';
    $type[':motscles'] = PDO::PARAM_STR;
    $where[]           = 'i.restranscription LIKE :motscles';
     
    if (isset($_POST['audio'])) {
        $cac = (int)$_POST['audio'];
        $data[':audio'] = ($cac === 0) ? 0 : 1;  // on s'assure que l'on aura que des 1 ou des 0
        $type[':audio'] = PDO::PARAM_INT;
        $where[]        = 'i.audio = :audio';
    }
     
    if (isset($_POST['video'])) {
        $cac = (int)$_POST['video'];
        $data[':video'] = ($cac === 0) ? 0 : 1;  // on s'assure que l'on aura que des 1 ou des 0
        $type[':video'] = PDO::PARAM_INT;
        $where[]        = 'i.video = :video';
    }
     
    if (isset($_POST['document'])) {
        $cac = (int)$_POST['document'];
        $data[':document'] = ($cac === 0) ? 0 : 1;  // on s'assure que l'on aura que des 1 ou des 0
        $type[':document'] = PDO::PARAM_INT;
        $where[]           = 'i.document = :document';
    }
     
    $where = empty($where) ? '' : ' WHERE '. implode(' AND ', $where);
     
    $sql = <<<sql
    SELECT GROUP_CONCAT( CONCAT(t.civilite, ' ', t.prenom, ' ', t.nom, ', ', t.qualite) ORDER BY t.nom SEPARATOR ' ~~ ') AS groupe, i.id, i.nom_fichier
    FROM temoins as t
       INNER JOIN asso_temoins at  ON at.temoin_id = t.id
       INNER JOIN temoignages  i   ON i.id         = at.temoignage_id
    {$where}
    GROUP BY
       i.id
    ORDER BY
        i.nom_fichier
    sql;
     
    $stmt = $pdo->prepare($sql);
     
    // injection des valeurs dynamiques
    foreach ($data as $tag => $v) {
        $stmt->bindValue($tag, $v, $type[$tag]);
    }   
    $exec = $stmt->execute();
    $data = $stmt->fetchAll;
     
    if (empty($data)) {
       echo 'Aucun résultat<br /><a href="recherche.php">Retour au formulaire de recherche</a>';
    } else {
        $nb = count($data);
        echo '<p>', $nb, ' résultat', ($nb > 1) ? 's' : '', '</p';
     
        // échappement des caractères dangereux
        $hsc = function($p) { return htmlspecialchars($p, ENT_QUOTES, 'utf-8'); };
     
        foreach ($data as $v) {
            echo <<<html
    <p><a href="temoignage.php?id={$v['id']}">Témoignage de&nbsp;{$hsc($v['groupe'])}</a></p>
    html;
        }
    }
    comme toujours je n'ai rien testé, ça sort du four.
    par contre ça serait bien que tu indiques la version du PHP en production.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    1-
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (isset($_POST['document'])) {
        $cac = (int)$_POST['video'];
    video au lieu de document ligne 48.


    2- On est d'accord qu'ici, si une checkbox N'est PAS cochée, la requête sera "PAS de....".

    Perso, j'aurais mis des boutons radio : Tous / Oui / Non
    • Tous : (rien dans la requête)
    • Oui : "... = 1"
    • Non : "... = 0"

    C'est plus clair.

  6. #6
    Membre averti
    Homme Profil pro
    Conseil en assistance à maîtrise d'ouvrage
    Inscrit en
    Juin 2019
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Conseil en assistance à maîtrise d'ouvrage

    Informations forums :
    Inscription : Juin 2019
    Messages : 28
    Par défaut
    Citation Envoyé par jreaux62 Voir le message
    ...Perso, j'aurais mis des boutons radio : Tous / Oui / Non
    Bonjour et merci, je viens de corriger en effet.
    Cela dit ça ne change rien par rapport à la réponse que je viens de poster... (les cases à cocher ne semblent pas prises en compte)

    C'est-à-dire, trois groupes de boutons radio, un pour chaque critère vidéo / audio / documents ?
    ça permettrait d'afficher éventuellement les interviews qui n'ont pas de vidéo, etc. je n'y avais pas pensé mais c'est intéressant !

  7. #7
    Membre averti
    Homme Profil pro
    Conseil en assistance à maîtrise d'ouvrage
    Inscrit en
    Juin 2019
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations professionnelles :
    Activité : Conseil en assistance à maîtrise d'ouvrage

    Informations forums :
    Inscription : Juin 2019
    Messages : 28
    Par défaut
    Merci !
    En effet c'est plus compliqué, mais j'ai compris le raisonnement, c'est déjà ça (sauf la partie "injection des valeurs dynamiques"...).
    ça marche très bien pour la recherche du mot-clé tapé, par contre il ne prend pas en compte les cases à cocher (on dirait qu'il arrête la clause WHERE avant le premier AND ?)
    D'ailleurs, puisque si les cases à cocher sont isset, la valeur recherchée est forcément 1 dans la table, je me demandais si on n'aurait pas pu écrire plus simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (isset($_POST['audio'])) {
        $where[]        = 'i.audio = 1';
    }
    au lieu de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    if (isset($_POST['audio'])) {
        $cac = (int)$_POST['audio'];
        $data[':audio'] = ($cac === 0) ? 0 : 1;  // on s'assure que l'on aura que des 1 ou des 0
        $type[':audio'] = PDO::PARAM_INT;
        $where[]        = 'i.audio = :audio';
    }
    ?

    Autre problème : ce code semble rendre obligatoire la saisie d'un mot-clé. Dans "interception d'absence de mot-clé" : en fait ce message doit s'afficher si aucun champ du formulaire n'est utilisé (sachant que dans tous les cas on reçoit au moins un champ motscles vide).
    C'est vrai que je ne l'avais pas précisé, désolé, mais en fait ce champ de mot-clé n'est pas obligatoire (on pourrait juste filtrer "documents" sur toutes les interviews par exemple).

    *PHP 7.2.10 / mySQL 5.7.23

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

Discussions similaires

  1. Interbase requête SQL qui ne fonctionne pas
    Par colorid dans le forum InterBase
    Réponses: 6
    Dernier message: 20/11/2007, 17h36
  2. Requête hibernate qui ne fonctionne pas
    Par sheura dans le forum Hibernate
    Réponses: 4
    Dernier message: 28/09/2007, 16h20
  3. requête match qui ne fonctionne pas.
    Par sam01 dans le forum Requêtes
    Réponses: 3
    Dernier message: 29/05/2006, 20h28
  4. [MySQL] Requête update qui ne fonctionne pas
    Par Sylvain245 dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 05/12/2005, 16h40
  5. [SQL] Requête à jointure qui ne fonctionne pas
    Par Bensor dans le forum Langage SQL
    Réponses: 2
    Dernier message: 09/12/2004, 16h10

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