[RESOLU] Formulaire de recherche multicritère + url rewriting

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 01:23

Bonjour,

Nouveau en PHP, je suis en train de coder une page avec un formulaire de recherche multicritères qui me pose des problèmes depuis quelques jours.

En utilisant l'URL rewriting, j'ai d'abord rencontré des problèmes pour obtenir mes informations $ _POST. J'ai résolu mon problème en ajoutant le flag [QSA] à ma règle (tout d'abord, est-ce correct de l'utiliser pour un $ _POST ?).

Sauf que j'ai maintenant d'autres problèmes.
1) J'ai maintenant de jolis messages "Array to string conversion" sur les commentaires de chacun des ID que je demande (mais j'ai mes ID en affichant un var_dump de mon $ _POST).
2) J'ai également un message "Cannot modify header information - headers already sent by..." (et c'est là que je me demande si le flag [QSA] est vraiment le bon).
3) Ma requête SQL n'est pas exécutée (ma table est vide en affichant un var_dump de la variable dans laquelle je souhaite stocker les informations demandées par la requête).

Voici mon phtml, mon code PHP ainsi que ma RewriteRule:

Code : Tout sélectionner

RewriteRule ^trouver_un_jardin$ model/frontend/trouver.php [QSA]

Code : Tout sélectionner

<select name="idType[]" class="form-control my-5"> <?php foreach ($rechercheType as $searchType) : ?> <option <?php echo $searchType["selected"] ?> value="<?php echo $searchType["id"] ?>"><?php echo $searchType["type_de_jardin"] ?></option> <?php endforeach ?> </select> <select name="idTaille[]" class="form-control my-5"> <?php foreach ($rechercheTaille as $searchTaille) : ?> <option <?php echo $searchTaille["selected"] ?> value="<?php echo $searchTaille["id"] ?>"><?php echo $searchTaille["taille"] ?></option> <?php endforeach ?> </select> <select name="idZone[]" class="form-control my-5"> <?php foreach ($rechercheZone as $searchZone) : ?> <option <?php echo $searchZone["selected"] ?> value="<?php echo $searchZone["id"] ?>"><?php echo $searchZone["zone"] ?></option> <?php endforeach ?> </select> <select name="idPrix[]" class="form-control my-5"> <?php foreach ($recherchePrix as $searchPrix) : ?> <option <?php echo $searchPrix["selected"] ?> value="<?php echo $searchPrix["id"] ?>"><?php echo $searchPrix["prix"] ?></option> <?php endforeach ?> </select> </div> <div class="form-group px-5"> <button class="btn btn-form btn-block" type="submit" name="action" value="search">Trouver</button> </div> <?php print_r($_POST) ?> <?php var_dump($rechercheJardins) ?> </form>

Code : Tout sélectionner

if (isset($_POST["action"]) && $_POST["action"] == "search") { $req = "SELECT jardins.id, jardins.image, jardins.alt, jardins.titre, jardins.description, jardins.prix FROM jardins JOIN recherche_jardin ON jardins.id = id_jardin WHERE id_recherche_type = :idType AND id_recherche_taille = :idTaille AND id_recherche_zone = :idZone AND id_recherche_prix = :idPrix"; $stm = $sqlQuery->prepare($req); $postValue = $_POST; unset($postValue["action"]); $stm->execute($postValue); $rechercheJardins = $stm->fetchall(PDO::FETCH_ASSOC); header("location: trouver_un_jardin"); };
Si vous pouviez m'aider, je vous en serai bien reconnaissant.

Merci d'avance.

Mammouth du PHP | 1341 Messages

12 mars 2020, 01:31

1. il faudrait le message d'erreur complet et nous donner le code php correspondant
2. avant un header("location: trouver_un_jardin"); il ne faut pas écrire quelque chose
3. le header appelle une nouvelle page, tout ce qui est fait avant le header est perdu. il ne faut donc pas utiliser un header dans ce cas là.

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 09:12

Bonjour, merci pour ta réponse.

Je me retrouve donc avec 4 fois le message "Notice: Array to string conversion in C:\wamp64\www\locater\model\frontend\trouver.php on line 38", ce qui correspond à la ligne de code "$stm->execute($postValue);".

Et "Warning: Cannot modify header information - headers already sent by (output started at C:\wamp64\www\locater\model\frontend\trouver.php:38) in C:\wamp64\www\locater\model\frontend\trouver.php on line 41" ce qui correspond au " header("location: trouver_un_jardin");".

Donc si je comprends bien, le header location n'est pas du tout a utiliser tout le temps dans ce genre de situation. Dans ce cas la, par quoi le remplacer?

Merci d'avance pour vos réponses.

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 11:14

Bon, en supprimant les [] dans mes "name" (n'ayant pas besoin d'un tableau ici dans mon cas) dans mon phtml, je n'ai plus aucune erreur d'affiché.

Par contre, en faisant un echo de la variable dans laquelle je veux stocker les infos de ma requête select, cela me dis que ma variable n'existe pas (et donc, je n'ai pas les infos de ma requête).

Merci d'avance pour vos réponses.

Mammouth du PHP | 1341 Messages

12 mars 2020, 19:57

Donc si je comprends bien, le header location n'est pas du tout a utiliser tout le temps dans ce genre de situation. Dans ce cas la, par quoi le remplacer?
la requête sql doit être exécutée dans le même script que l'affichage du résultat de la requête, dans model/frontend/trouver.php si ce fichier affiche le formulaire et aussi le résultat de la recherche.

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 22:02

Hé bien, techniquement, "trouver_un_jardin" et "trouver.php" sont les mêmes fichiers. La seul chose, c'est l'url rewriting avec le flag QSA qui, d'après ce que j'ai compris de la doc, sert justement pour ce genre de cas.

Aurais-je mal compris?

Mammouth du PHP | 1341 Messages

12 mars 2020, 22:25

non

au lieu de faire une redirection qui fait perdre le code exécuté avant, il faut afficher le contenu du résultat du select.

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 22:50

Donc killer le "header location", c'est bien ça?

Mais même dans ce cas la, cela ne fonctionne pas, un var_dump de la variable dans laquelle je tente de stocker les infos de ma requête m'indique que la variable n'est pas définie.

Ce qui est un peu fort puisque je la définie après l’exécution en lui demandant de stocker les infos demandé dans un tableau.

Cela fait plusieurs jours que je bloque sur cette fonctionnalité et c'est la dernière nécessaire pour finaliser mon site. Vraiment prise de tête celle la.

Mammouth du PHP | 1341 Messages

12 mars 2020, 23:12

on peut avoir le code en entier ?

midorijin
Invité n'ayant pas de compte PHPfrance

12 mars 2020, 23:25

Bien sur, php:

Code : Tout sélectionner

<?php $content = "../../view/frontend/trouver.phtml"; $title = "Trouver un jardin"; function coupe($text, $nb = 170) { if (strlen($text) > $nb) { $pos = $nb; while ($text[$pos] <> ' ') { $pos--; }; $text = substr($text, 0, $pos) . '...'; }; return $text; }; require_once("../../controller/controller.php"); $req = ("SELECT `id`, `type_de_jardin`, `selected` FROM `recherche_type`"); $stm = $sqlQuery->prepare($req); $stm->execute(); $rechercheType = $stm->fetchall(PDO::FETCH_ASSOC); $req = ("SELECT `id`, `taille`, `selected` FROM `recherche_taille`"); $stm = $sqlQuery->prepare($req); $stm->execute(); $rechercheTaille = $stm->fetchall(PDO::FETCH_ASSOC); $req = ("SELECT `id`, `zone`, `selected` FROM `recherche_zone`"); $stm = $sqlQuery->prepare($req); $stm->execute(); $rechercheZone = $stm->fetchall(PDO::FETCH_ASSOC); $req = ("SELECT `id`, `prix`, `selected` FROM `recherche_prix`"); $stm = $sqlQuery->prepare($req); $stm->execute(); $recherchePrix = $stm->fetchall(PDO::FETCH_ASSOC); if (isset($_POST["action"]) && $_POST["action"] == "search") { $req = "SELECT jardins.id, jardins.image, jardins.alt, jardins.titre, jardins.description, jardins.prix FROM jardins JOIN recherche_jardin ON jardins.id = id_jardin WHERE id_recherche_type = :idType AND id_recherche_taille = :idTaille AND id_recherche_zone = :idZone AND id_recherche_prix = :idPrix"; $stm = $sqlQuery->prepare($req); $postValue = $_POST["action"]; unset($postValue["action"]); $stm->execute($postValue); $rechercheJardins = $stm->fetchall(PDO::FETCH_ASSOC); header("location: trouver_un_jardin"); }; // En attendant que la requête de recherche fonctionne $req = "SELECT `id`, `image`, `alt`, `titre`, `description`, `taille_jardin`, `prix` FROM `jardins`"; $stm = $sqlQuery->prepare($req); $stm->execute(); $jardin = $stm->fetchall(PDO::FETCH_ASSOC); require_once("layout.php");
phtml:

Code : Tout sélectionner

<main class="page"> <section class="d-block d-sm-none" style="height: 40px"></section> <section class="d-none d-sm-block" style="height: 20px"></section> <section class="clean-block features background-header"> <div class="container mt-4"> <div class="block-heading"> <h1 class="text-info font-weight-bold">Trouver un jardin</h1> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc quam urna, dignissim nec auctor in, mattis vitae leo.</p> </div> <div class="flex-row align-items-center row justify-content-center"> <div class="col-12 col-md-6"> <!-- Formulaire de recherche de terrain --> <form class="text-center" action="trouver_un_jardin" method="POST"> <h2 class="pt-3"><b>Recherher un jardin</b></h2> <div class="form-group px-3"> <select name="idType" class="form-control my-5"> <?php foreach ($rechercheType as $searchType) : ?> <option <?php echo $searchType["selected"] ?> value="<?php echo $searchType["id"] ?>"><?php echo $searchType["type_de_jardin"] ?></option> <?php endforeach ?> </select> <select name="idTaille" class="form-control my-5"> <?php foreach ($rechercheTaille as $searchTaille) : ?> <option <?php echo $searchTaille["selected"] ?> value="<?php echo $searchTaille["id"] ?>"><?php echo $searchTaille["taille"] ?></option> <?php endforeach ?> </select> <select name="idZone" class="form-control my-5"> <?php foreach ($rechercheZone as $searchZone) : ?> <option <?php echo $searchZone["selected"] ?> value="<?php echo $searchZone["id"] ?>"><?php echo $searchZone["zone"] ?></option> <?php endforeach ?> </select> <select name="idPrix" class="form-control my-5"> <?php foreach ($recherchePrix as $searchPrix) : ?> <option <?php echo $searchPrix["selected"] ?> value="<?php echo $searchPrix["id"] ?>"><?php echo $searchPrix["prix"] ?></option> <?php endforeach ?> </select> </div> <div class="form-group px-5"> <button class="btn btn-form btn-block" type="submit" name="action" value="search">Trouver</button> </div> <?php var_dump($rechercheJardins) ?> </form> <!-- Fin formulaire de recherche de terrain --> </div> </div> </div> </section> <section class="background-footer"> <div class="container"> <div class="row text-center pb-5 justify-content-around"> <?php foreach ($jardin as $jard) : ?> <div class="col-md-6 col-lg-4 mb-3"> <div class="card h-100"> <div class="card-body"> <img class="card-img-top w-100 d-block rounded" src="<?php echo $jard["image"] ?>" alt="<?php echo $jard["alt"] ?>"> <h4 class="card-title mt-4 " style="height: 50px"><?php echo $jard["titre"] ?></h4> <p class="card-text"><?php echo coupe($jard["description"]) ?></p> <h5 class="text-muted card-subtitle my-3"><b>Taille:</b> <?php echo $jard["taille_jardin"] ?>m²</h6> <h5 class="text-muted card-subtitle my-3"><b>Prix:</b> <?php echo $jard["prix"] ?>€</h6> <a class="card-link btn btn-form mt-3" style="width: 150px" href="jardin<?php echo $jard["id"] ?>">Voir le jardin</a> </div> </div> </div> <?php endforeach ?> </div> </div> </section> </main>
Tu veux aussi les layout?

Mammouth du PHP | 1341 Messages

13 mars 2020, 00:48

SELECT jardins.id, jardins.image, jardins.alt, jardins.titre, jardins.description, jardins.prix FROM jardins JOIN recherche_jardin ON jardins.id = id_jardin WHERE id_recherche_type = :idType AND id_recherche_taille = :idTaille AND id_recherche_zone = :idZone AND id_recherche_prix = :idPrix

ça me parait très bizarre. cette requete fonctionne dans phpmyadmin ? tant que ce n'est pas le cas, inutile de vouloir le faire marcher dans le code php.
if (isset($_POST["action"]) && $_POST["action"] == "search") {
    $req = "SELECT jardins.id, jardins.image, jardins.alt, jardins.titre, jardins.description, jardins.prix FROM jardins WHERE id_recherche_type = :idType AND id_recherche_taille = :idTaille AND id_recherche_zone = :idZone AND id_recherche_prix = :idPrix";
    $stm = $sqlQuery->prepare($req);
    $postValue = $_POST["action"];
    unset($postValue["action"]);
    $stm->execute($postValue);
    $jardin = $stm->fetchall(PDO::FETCH_ASSOC);
}
else{
// En attendant que la requête de recherche fonctionne
$req = "SELECT `id`, `image`, `alt`, `titre`, `description`, `taille_jardin`, `prix` FROM `jardins`";
$stm = $sqlQuery->prepare($req);
$stm->execute();
$jardin = $stm->fetchall(PDO::FETCH_ASSOC);
}
1er affichage, cela affiche le formulaire et tous les jardins. quand on soumet le formulaire, cela affiche le résultat du filtre (avec tous les champs de filtre dans une seule table) sur les 4 champs. ce code ne permet pas de filtrer sur un seul champ, c'est obligatoirement sur les 4.

midorijin
Invité n'ayant pas de compte PHPfrance

13 mars 2020, 08:59

Bonjour,

Oui, j'ai bien sur fait des testes en amont dans phpmyadmin afin de vérifier si la requête fonctionne bien et c'est le cas (selon les différents id que je met à la place de :idType, :idTaille, :idZone et :IdPrix, j’obtiens bien les différents jardins qui leur sont associés.

Oui, je veux bien ne filtrer "que" sur les 4 champs et non pas sur un seul

midorijin
Invité n'ayant pas de compte PHPfrance

13 mars 2020, 09:21

Edit : Je vois que dans le code que tu m'a renvoyé, tu a killer la jointure.

J'aurais peu être du en parler, je dispose d'un table jardins (qui contient toutes les infos des jardins), des tables recherche_taille, recherche_type, recherche_zone et recherche_prix (qui contiennent chacune différentes catégories, du genre la table prix entre 0-50€, 50-100€, 100-200€) et toutes relier à une table recherche_jardin.

Si ça peu aider.

Mammouth du PHP | 1341 Messages

13 mars 2020, 15:17

je l'ai virée car la table recherche_jardin ne sert à rien, les 4 champs id* doivent être dans la table jardins.

midorijin
Invité n'ayant pas de compte PHPfrance

14 mars 2020, 15:43

Bonjour,

J'ai mis en application tes recommandation, il y a déjà du mieux, mais ça ne résout pas encore le problème.

Donc j'ai killé la table recherche_jardin et lié les différents critère de recherche à ma table jardin.

A la suite de quoi, ma variable de stockage est enfin reconnu (sans aucun critère de sélection, je vois la totalité de mes jardins dans mon var_dump). Par contre, des que je sélectionne les critères, j'obtiens le message "Fatal error: Uncaught Error: Cannot unset string offsets in C:\wamp64\www\locater\model\frontend\trouver.php on line 66", j'en ai donc déduis que je devais killer le "unset($postValue["action"]);".

Après ça, j'obtiens le message "Warning: PDOStatement::execute() expects parameter 1 to be array, string given in C:\wamp64\www\locater\model\frontend\trouver.php on line 67", donc j'ai mis l'execute de mon $postValue dans un array ("$stm->execute(array($postValue));").

Par contre, j'ai maintenant le double message "Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in C:\wamp64\www\locater\model\frontend\trouver.php on line 67" et "PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in C:\wamp64\www\locater\model\frontend\trouver.php on line 67".