Concaténation variable requête SQL SELECT

Carpediem
Invité n'ayant pas de compte PHPfrance

07 oct. 2014, 19:32

Bonjour à toutes et à tous,

Je viens reposter après avoir cibler le souci auquel je suis confronté ici php-debutant/souci-affichage-requete-sq ... ml#p428619

Après avoir refait mes scripts et cherché une solution, j'en arrive à la conclusion suivante :

1. Le souci semble venir de la concaténation de mes variables (j'ai essayé également avec l'appel d'un tableau en requête "prepare")
2. Quand je valide mon formulaire de recherche en choisissant comme type de recherche "l'identifiant" (5 chiffres), ma requête s'affiche avec mon code actuel mais si je choisi dans mon type de recherche "nom" et que je tape un nom d'une personne présente dans ma bdd, tout s'éxécute sans erreur mais rien ne s'affiche.

Il semble évident que le script ne contient pas d'erreur majeur et que le souci vienne bien de la concaténation (enfin je pense)

Voici les codes (pas fini bien entendu, ils sont simplifiés pour limiter les erreurs dans l'immédiat)

formulaire :
<form action="recherche......../.......php" method="post" enctype="multipart/form-data">

<p>
<fieldset>
    <legend>Rechercher</legend>
    
     <label for="type_recherche">Type de recherche par :</label> 
     <select name="type_recherche" id="type_recherche" required="required">
        <option value="ID">ID</option>
        <option value="identifiant_client">Identifiant</option>
        <option value="nom_client">Nom</option>
        <option value="prenom_client">Prénom</option>
        <option value="cp_client">Code Postal</option>
        <option value="telephone_client">Téléphone</option>
     </select>
     
     <input type="text" name="recherche" required="required" maxlength="40" />

     
</fieldset>

     <p><input type="submit" value="Lancer la recherche" name="envoyer"></p>
</p>
</form>
et le script de récupération des données et d'affichage depuis ma bdd
<?php

if (isset($_POST["envoyer"])) {

$etat = "erreur";

	// On récupère les champs du formulaire, et on arrange leur mise en forme
  
	// trim()  enlève les espaces en début et fin de chaine
  
  if (isset($_POST["recherche"])) { $_POST["recherche"]=trim(htmlspecialchars($_POST["recherche"])); }
  
  if (isset($_POST["type_recherche"])) { $_POST["type_recherche"]=trim(htmlspecialchars($_POST["type_recherche"])); }


  if (empty($_POST["recherche"])) { 
		$erreur="Vous n'avez saisi aucune recherche dans la case correspondante..."; 
	}
  elseif (empty($_POST["type_recherche"])) { 
		// On met dans erreur le message qui sera affiché
		$erreur="Vous n'avez saisi aucun type de recherche dans la case correspondante..."; 
	}
  elseif (!is_string($_POST["recherche"])) { 
		// On met dans erreur le message qui sera affiché
		$erreur="Votre case recherche contient des caractères spéciaux..."; 
	}
  elseif (!is_string($_POST["type_recherche"])) { 
		// On met dans erreur le message qui sera affiché
		$erreur="Votre case type de recherche contient des caractères spéciaux..."; 
	}  
  
  else { 
		$etat="ok";
    }
  }
  
if ($etat=="ok"){

$recherche=(strtoupper($_POST["recherche"]));
$type_recherche=(strtoupper($_POST["type_recherche"]));
              
  try
{
    $bdd = new PDO('mysql:host=localhost;dbname=mabasededonnes', 'root', '');
    $bdd->query("SET NAMES UTF8");
    $bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
}
catch(Exception $e)
{
        die('Erreur : '.$e->getMessage());
}


$recherche = $bdd->query('SELECT * FROM client WHERE "'.$type_recherche.'='.$recherche.'" ');

while ($donnees = $recherche->fetch())
{

?>
     <b>Date De Création :</b> <?php echo $donnees['jour_creation'] . '/' . $donnees['mois_creation'] . '/' . $donnees['annee_creation']; ?>
     <b>Identifiant :</b> <?php echo $donnees['identifiant_client']; ?><br />
     <b>Civilité :</b> <?php echo $donnees['civilite_client']; ?><br />
     <b>Nom :</b> <?php echo $donnees['nom_client']; ?><br />
     <b>Prenom :</b> <?php echo $donnees['prenom_client']; ?><br />
     <b>Email :</b> <?php echo $donnees['email_client']; ?><br />
     <b>Téléphone :</b> <?php echo $donnees['telephone_client']; ?><br />
     <b>Adresse :</b> <?php echo $donnees['adresse_client']; ?><br />
     <b>Code Postal :</b> <?php echo $donnees['cp_client']; ?><br />
     <b>Ville :</b> <?php echo $donnees['ville_client']; ?><br />
     <b>Résidence :</b> <?php echo $donnees['residence_client']; ?><br />
     <b>Bâtiment :</b> <?php echo $donnees['batiment_client']; ?><br />
     <b>Escalier :</b> <?php echo $donnees['escalier_client']; ?><br />
     <b>Etage :</b> <?php echo $donnees['etage_client']; ?><br />
     <b>Digicode :</b> <?php echo $donnees['digicode_client']; ?><br />
     <b>Appartement :</b> <?php echo $donnees['appartement_client']; ?><br />
     <b>Type Cheveux :</b> <?php echo $donnees['type_cheveux']; ?><br />
     <b>Nature Cheveux :</b> <?php echo $donnees['nature_cheveux']; ?><br />
     <b>Examen Cuir Chevelu :</b> <?php echo $donnees['examen_cuir']; ?><br />
     <b>Shampoing :</b> <?php echo $donnees['shampoing']; ?><br />
     <b>Couleur Naturelle :</b> <?php echo $donnees['couleur_naturelle']; ?><br />
     <b>% Cheveux Blanc :</b> <?php echo $donnees['pourcentage_blanc']; ?><br />
     <b>Observations :</b> <?php echo $donnees['observation_client']; ?>
     

   
<?php
}
 
$recherche->closeCursor(); // Termine le traitement de la requête

}

elseif ($etat=="erreur"){ 
		// On affiche le message correspondant à l'erreur
		echo "<h4>$erreur <br /><br />
    Retour à la page <a href=\"index.php\">Accueil</a> ou à la page <a href=\"........../............./.............../.php\">Gestion Client</a></h4>"; 
	}

else {
    header('Location: ........./........../........./.php');
}

	?>
PS : J'ai essayé différentes concaténation mais rien n'y fait.

Merci d'avance pour votre aide

Cordialement

Mammouth du PHP | 2278 Messages

08 oct. 2014, 15:09

Au lieu de:
$recherche = $bdd->query('SELECT * FROM client WHERE "'.$type_recherche.'='.$recherche.'" ');
mettre:
$requete = "SELECT * FROM client WHERE "'.$type_recherche.'='.$recherche.'";
print "$requete"; die();
pour voir ce que tu fais.
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ynx
Mammouth du PHP | 586 Messages

08 oct. 2014, 15:10

Salut,

Pour commencer, appliquer un htmlentities sur les données destinées à être utilisé dans une requête sql n'est pas une bonne pratique. Comme son nom l'indique, htmlentities doit être utilisée pour afficher des données sensibles dans un document html.
// On récupère les champs du formulaire, et on arrange leur mise en forme
$_POST["recherche"] = isset($_POST["recherche"]) ? trim($_POST["recherche"]) : '';
$_POST["type_recherche"] = isset($_POST["type_recherche"]) ? trim($_POST["type_recherche"]) : '';
As tu essayer d'afficher ta requête pour voir si elle était correcte ? Cela te permettrait de l’exécuter directement dans un client sql (tel que PhpMyAdmin par exemple) :
$query = "SELECT * FROM client WHERE " . $type_recherche  . " = " . $bdd->quote($recherche);

// debug
echo '<pre>' . $query . '</pre>'; // pour voir et tester ta requête dans PhpMyAdmin

$recherche = $bdd->query($query);
Ne pas oublier de protéger tes requêtes contre les injections sql avec la méthode PDO::quote(). On ne peut pas utiliser cette méthode pour un nom de colonne, la solution la plus sur serait donc de passer par une liste blanche pour $type_recherche.

L'égalité en sql correpond à une recherche stricte : la valeur du champ $type_recherche doit correspondre exactement à $recherche. Si tu veux une recherche plus large, tu peux utiliser l'opérateur LIKE comme ceci :
$query = "SELECT * FROM client WHERE " . $type_recherche  . " LIKE " . $bdd->quote('%' . $recherche . '%');
A toi de faire tes tests pour savoir laquelle correspond le mieux à ton besoin.

Carpediem
Invité n'ayant pas de compte PHPfrance

08 oct. 2014, 17:08

Bonsoir,

Merci pour les conseilles. Concernant vos idées, rien n'y fait mon script fonctionne quand je recherche un identifiant mais pas quand je recherche un nom.

Image

Les erreurs en bas viennent de ce script
$query = "SELECT * FROM client WHERE " . $type_recherche  . " = " . $bdd->quote($recherche);

// debug
echo '<pre>' . $query . '</pre>'; // pour voir et tester ta requête dans PhpMyAdmin

$recherche = $bdd->query($query);
mais ce qu'il y a au dessus vient de ma requete
$recherche = $bdd->query('SELECT * FROM client WHERE "'.$type_recherche.'='.$recherche.'" ');
ce résultat est encore une fois possible si je demande par mes variables WHERE identifiant_client=97692 mais ne fonctionne pas quand les variables sont WHERE nom_client=AZERTY

Je ne comprends pas

ViPHP
xTG
ViPHP | 7331 Messages

08 oct. 2014, 18:33

$recherche = $bdd->query('SELECT * FROM client WHERE "'.$type_recherche.'='.$recherche.'" ');
ce résultat est encore une fois possible si je demande par mes variables WHERE identifiant_client=97692 mais ne fonctionne pas quand les variables sont WHERE nom_client=AZERTY

Je ne comprends pas
Il te faut dans ce cas pour gérer les chaînes de caractères mettre des quotes (mais surtout au bon endroit).
En partant du principe que $type_recherche est un nom de colonne potable :
$recherche = $bdd->query('SELECT * FROM client WHERE '.$type_recherche.'="'.$recherche.'" ');

Mammouth du PHP | 2278 Messages

09 oct. 2014, 09:09

Suggestion;
<?PHP
$bdd = new PDO('sqlite:/home/bilou/music.sql3');
$type_recherche = "client";
$recherche = "Amfred";
$type_recherche = $bdd->quote($type_recherche);
$recherche=$bdd->quote($recherche);
$requete = "SELECT * FROM client WHERE $type_recherche = $recherche";
print "$requete";
?>
Vanitas vanitatum et omnia vanitas
Mes derniers livres :
Sauvez les Mots chez BoD,
Tous les chemins mènent à ROM chez BoD

ynx
Mammouth du PHP | 586 Messages

09 oct. 2014, 16:26

$query = "SELECT * FROM client WHERE " . $type_recherche  . " LIKE " . $bdd->quote('%' . $recherche . '%');
soit avec ton exemple :
SELECT * FROM client WHERE nom_client LIKE '%AZERTY%'
-> retourne les clients dont le nom contient la chaine "AZERTY"

Attention, le nom des colonnes ne doivent pas être entourés de quotes (d'où la proposition d'utiliser une liste blanche).