bonjour a tous je debute en php et je voudrais realiser une recherche en fonction de d'un terme variable provenant d'un formulaire
ma table sql contient des article classe par id, titre, categorie, details, prix, note
je pense avoir peut etre mal introduit les variable des placeholders dans array mais je parvient pas a voir/corrigé mon erreur
voici le bout de code qui ne fonctionne pas
un var_dump() de $trouver me renvoi 'bool(false)'

$search = $_POST['search'];);
$search = strtolower($search);
$ordre = $_POST['ordre']; // variable qui est recupere d'un select qui est soit titre soit prix soit la note
$limit = $_POST['limit'];// variable qui est recupere egalement d'un select
// un echo de toute ces variables affiche correctement leur contenu
$st = $pdo->prepare("SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY ? LIMIT ?");
$st->execute(array("%".$search."%", "%".$search."%", $ordre, $limit));
$trouver = $st->fetch();"

par contre ceci fonctionne mais c'est insufisant
$search = $_POST['search'];);
$search = strtolower($search);
$ordre = $_POST['ordre']; // variable qui est recupere d'un select
$limit = $_POST['limit'];// variable qui est recupere egalement d'un select
$st = $pdo->prepare("SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY titre LIMIT 4");
$st->execute(array("%".$search."%", "%".$search."%"));
$trouver = $st->fetch();"

Ce que je veux
j'espere avoir été precis je voudrai faire fonctionner mon code au complet ou alors un moyen simple de realiser ma recherche detaillée merci d'avance

Ce que j'obtiens

rien et aucune erreur

14 réponses


JediDev
Réponse acceptée

Bon ok Carouge10, on va faire cela correctement avec ta piste.
"Je pensais justement que le htmlentities permettait d'éviter les injections SQL au niveau des formulaires ?"

Exemple qui fonctionne (chez moi) en prenant bien en compte les marqueurs ? de la requête SQL preparée, donc le LIMIT

$variable ="Br";
$variable = "%" . $variable . "%";
$limit = "3";
$ordre = "DESC";
$ReqSql = 'SELECT * FROM essai_notes WHERE Deno LIKE ? ORDER BY ? LIMIT ?';
$query = $db->prepare($ReqSql);

$query->bindParam(1, $variable, PDO::PARAM_STR, 12);
$query->bindParam(2, $ordre, PDO::PARAM_STR, 12);
$query->bindParam(3, $limit, PDO::PARAM_INT);
$query->execute();

$tests = $query->fetchAll();

Bonjour,
tu ne peux pas "binder" les varibles pour LIMIT comme cela, il faut forcément passer par bindvalue (je crois sinon c'est bindparam) de PDO

Bonsoir,
Regarde si tes variables sont bien formatées.
Avec ce code de mon côté j'arrive à utiliser une variable pour le LIMIT

$annee = "2021";
$limit = "3";
$ReqSql = 'SELECT * FROM livrecompte WHERE annee = ' . $annee . ' ORDER BY date ASC LIMIT ' . $limit;
$query = $db->query($ReqSql);
$livreCompte = $query->fetchAll(PDO::FETCH_OBJ);
var_dump($livreCompte);

Le var_dump me donne ceci:

array (size=3)
0 =>
object(stdClass)[3]
public 'IdLivre' => string '30' (length=2)
public 'annee' => string '2021' (length=4)
public 'trimestre' => string '1' (length=1)
public 'date' => string '2021-11-01' (length=10)
public 'facture' => string '0001' (length=4)
public 'client' => string 'JediDev' (length=7)
public 'prestation' => string 'Prestation' (length=10)
public 'montant' => string '1000.0' (length=6)
public 'encaissement' => string 'Carte Bleue' (length=11)
1 =>
object(stdClass)[4]
public 'IdLivre' => string '33' (length=2)
public 'annee' => string '2021' (length=4)
public 'trimestre' => string '1' (length=1)
public 'date' => string '2021-11-11' (length=10)
public 'facture' => string '2021-0001' (length=9)
public 'client' => string 'JediDev' (length=7)
public 'prestation' => string 'Site Vitrine avec administration' (length=32)
public 'montant' => string '52.0' (length=4)
public 'encaissement' => string 'Carte Bleue' (length=11)
2 =>
object(stdClass)[5]
public 'IdLivre' => string '32' (length=2)
public 'annee' => string '2021' (length=4)
public 'trimestre' => string '1' (length=1)
public 'date' => string '2021-11-20' (length=10)
public 'facture' => string '2021-0001' (length=9)
public 'client' => string 'JediDev' (length=7)
public 'prestation' => string 'Site Vitrine avec administration' (length=32)
public 'montant' => string '2222.0' (length=6)
public 'encaissement' => string 'Carte Bleue' (length=11)

attention car avec ce dernier code suivant comment tu t'adaptes, tu peux avoir des injections sql car il n'est pas préparer

meliod
Auteur

bonjour et merci de me repondre aussi rapidement mais je ne comprend pas toujours comment proceder je me doute que l'erreur vient de la maniere dont j'ai ecris les variables apres avoir prepare la requete y'a t'il un moyen de mieux ecrire cela ? ou de binder ces parametres j'ai essaye pas mal de chose meme les moins evidentes
dans ma requette sql
$st = $pdo->prepare("SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY ? LIMIT ?");
normalement l'utilisateur doit faire une reherche dans la table article et peut grace à 3 select ranger les resultat d'abord selon leurs prix, titre,note et marque (qui sont des colonnes de ma table article ensuite par ordre croisant ou decroisant et enfin preciser le nombre de resultat afficher j'essaye d'implementer cela en me basant sur le bout de code qui fonctionne mais j'y arrive pas

meliod,
1) Je suis entièrement d'accord avec Carouge10, il faut bien penser à éviter l'injection SQL (SQLi). Mon exemple est sur un projet offline.

J'aurais tendance à essayer ceci :
$search = "%" . $search . "%" // préparer avant ta variable pour le LIKE
$ordre = $_POST['ordre'];
$limit = htmlentities($_POST['limit']); // Pour échapper la valeur du POST et ainsi éviter l'injection sur cette variable.
$ReqSql = "SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY ? LIMIT" . $limit; // préparer ta requête
$st = $pdo->prepare($ReqSql);
$st->execute($search,$search,$ordre);
$trouver = $st->fetchAll();

surtout pas de htmlentities. c'est pas pour ça.
j'ai donné la solution dans mon 1er

voila cest plus correct.
j'ai toujours eu un doute sur le limit entre bindvalue et bindparam.

meliod
Auteur

merci bien carouge10 et jediDev je me suis bassé sur ton code et ca marche bien je voudrai juste ajouter par exemple une autre variable du genre
$ReqSql = 'SELECT * FROM essai_notes WHERE Deno LIKE ? ORDER BY ? ? LIMIT ?'; pour que le classement se fasse en fonction de la table colonne Deno par exemple
quand j'essaie de le faire rien ne fonctionne j'ai l'impression qu'il ya un truc que je saisie pas

et quel est le code de ton essai ?

Bonjour,

Je te propose une autre méthode : les paramètres nommés.

$ReqSql = 'SELECT * FROM essai_notes WHERE Deno LIKE :Deno ORDER BY :ordre LIMIT :limit';
$query = $db->prepare($ReqSql);
$query->bindParam(':Deno', $variable, PDO::PARAM_STR, 12);
$query->bindParam(':ordre', $ordre, PDO::PARAM_STR, 12);
$query->bindParam(':limit', $limit, PDO::PARAM_INT);
$query->execute();
$tests = $query->fetchAll();
meliod
Auteur

voici mon code

$par ="prix";// par exemple
$variable ="o"; // par exemple
$variable = "%" . $variable . "%";
$limit = "5"; // par exemple
$ordre = "DESC"; // par exemple
$ReqSql = "SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY
(CASE WHEN $par = prix THEN prix END) ?

LIMIT ?";
$query = $pdo->prepare($ReqSql);
$query->bindParam(1, $variable, PDO::PARAM_STR, 12);
$query->bindParam(2, $variable, PDO::PARAM_STR, 12);
$query->bindParam(3, $ordre, PDO::PARAM_STR, 12);
$query->bindParam(4, $limit, PDO::PARAM_INT);
$query->execute();
$trouver = $query->fetch();

si j'ai utiliser case when c'est en dernier recour car j'arrivai pas a utilise les placeholders avec bindparam

meliod
Auteur

merci a tous j'ai finalement resolu mon probleme en utilisant swicht et en concanetant le nom de la colonne et l'ordre voulu
cela me permet en meme temps d'eviter les injection sql je pense c'est pas tres esthétique mais ca marche bien
voici un extrait de mon code

$concat = $par.$ordre;
switch ($concat) {
case "titreASC":
$ReqSql = "SELECT FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY titre ASC LIMIT ?";
break;
case "titreDESC":
$ReqSql = "SELECT
FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY titre DESC LIMIT ?";
break;
case "prixASC":
$ReqSql = "SELECT FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY prix ASC LIMIT ?";
break;
case "prixDESC":
$ReqSql = "SELECT
FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY prix DESC LIMIT ?";
break;
case "notegASC":
$ReqSql = "SELECT FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY noteg ASC LIMIT ?";
break;
case "notegDESC":
$ReqSql = "SELECT
FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY noteg DESC LIMIT ?";
break;
case "modelASC":
$ReqSql = "SELECT FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY model ASC LIMIT ?";
break;
case "modelDESC":
$ReqSql = "SELECT
FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY model DESC LIMIT ?";
break;
default:
$ReqSql = "SELECT * FROM article WHERE titre LIKE ? OR details LIKE ? ORDER BY prix ASC LIMIT ?";

           }

$query = $pdo->prepare($ReqSql);
$query->bindParam(1, $variable, PDO::PARAM_STR, 12);
$query->bindParam(2, $variable, PDO::PARAM_STR, 12);
$query->bindParam(3, $limit, PDO::PARAM_INT);
$query->execute()

c'est bien.
tu pourrais optimiser en utilisant la concaténation de te requête.
tu as le début de déjà construit et fonction d'où tu passes dans la boucle, tu ajoutes la suite. enfin après le switch, tu ajoutes la fin.
n'oublie pas de passer ton sujet en