[RESOLU] Affichage d'un menu et sous-menu dynamiques

Eléphant du PHP | 65 Messages

30 déc. 2021, 21:17

Bonjour,
Je galère à afficher les catégories et sous-catégories dans mon menu dynamique en récupérant l'id. Si vous pouvez m'apporter votre aide :)
L'objectif c'est c'est de faire apparaitre les annonces par catégories. Mes tables annonces, images, catégories et villes étant liées comme le montre la photo: https://imgur.com/a/KCiYnPG
Je cherche à éviter de mélanger les id, sinon le programme attribue à chaque annonce une image qui ne lui appartient pas. Il faut donc que j'intègre les tables annonces, villes, et categories pour l'affichage.
Ce qui me parait logique, voila ce que j'ai fait, mais il me reste le lien pour accueil et titre.

Code : Tout sélectionner

function getAnnonces_byCategory($id_cat){ global $bdd; $sql_lang = $_SESSION['lang']; $res = []; $sql = 'SELECT A.* Except A.id , C.id as id, C.nom_'.$sql_lang.' AS CATEGORIE ,V.ville_'.$sql_lang.' AS VILLE FROM annonces A LEFT JOIN categories C ON C.id = A.id_categorie LEFT JOIN villes V ON V.id = A.id_ville WHERE 1 = 1 AND id= :id_cat '; //pour Accueil et contact if($id_cat==1 || $id_cat==20){ $sql .= " "; //On ajoute un lien pour accueil et contact, mais comment? } //Pour les autres catégories if(1< $id_cat< 20){ $sql .= $sql .= " AND id = ".$id_cat." "; } //on fini par ajouter le order by $sql .= " ORDER BY created_date DESC" ; try { $req = $bdd->prepare($sql); $req->execute(); $res = $req->fetchAll(PDO::FETCH_ASSOC); } catch (Exception $e) { echo "Erreur dans la requête " . $sql; } // le temps des tests pour voir le résultat return $res; } function getAnnonces_Images_byCategory($id_cat){ global $bdd; $annonces = getAnnonces_byCategory($id_cat); $images = getImagesAnnonces(); $res = []; foreach ($annonces as $R) { $res[$R['id']] = $R; $imgs = !empty($images[$R['id']]) ? $images[$R['id']] : NULL; if(!empty($imgs)){ foreach($imgs as $I){ $res[$R['id']]['images'][] = !empty($I['IMG']) ? $I['IMG'] : null; } }else{ $res[$R['id']]['images'] = null; } } return $res; }
Et dans la page affichage.php:

Code : Tout sélectionner

<?php $id_cat = !empty($_GET['id']) ? trim($_GET['id']) : null; $annonces = getAnnonces_Images_byCategory($id_cat); foreach ($annonces as $annonce) { echo '<div class="annoncepubs">'; $images = !empty($annonce['images']) ? $annonce['images'] : ['/no_image.png']; // array if (!empty($images)) { //boucle sur les images echo'<div class="container">'; echo ' <div class="slider" >'; foreach ($images as $img) { echo '<img class ="active" style="width:90px; height:90px;" src="' . $img . '">'; } echo "</div>"; // fin div slider . echo '<div class="cont-btn" >'; echo ' <div class="btn-nav left" > <'; echo " </div>"; echo ' <div class="btn-nav right" > >'; echo " </div>"; echo "</div>"; echo "</div>"; // fin div container } echo "<span class='category'>" . $annonce['CATEGORIE'] . "</span>"; echo "<span class='title'>" . $annonce['titre'] . "</span>"; echo "<span class='comment'>" . $annonce['description'] . "</span>"; echo "<span class='price'>" . $annonce['prix'] . "</span>"; echo "<span class='date'>" . $annonce['created_date'] . "</span>"; echo "</div>"; // fin div annoncepubs } ?>

Eléphant du PHP | 65 Messages

04 janv. 2022, 19:16

Quelqu'un pour me guider s'il vous plait? Je suis toujours à la recherche de la solution

ynx
Mammouth du PHP | 586 Messages

04 janv. 2022, 21:01

Bonjour Max,

Désolé je dois être un peu fatigué mais je ne comprends pas bien ton problème.

Tu indiques vouloir ajouter des liens (des balises <a> ?) pour les pages accueil et contact dans ton menu dynamique mais le code que tu nous montre concerne l'affichage d'une liste d'annonces. On ne vois pas où et comment tu affiches ton menu sauf erreur de ma part.

Ou alors, sur les pages Accueil et Contact, tu veux afficher des annonces provenant d'une catégorie spécifique ou provenant de n'importe quelle catégorie ?

Pourrais tu reformuler et/ou préciser un peu plus ton problème stp ?
Quel est le résultat que tu obtiens et quel est le résultat que tu attends ?

Eléphant du PHP | 65 Messages

04 janv. 2022, 21:59

Bonjour ynx, merci pour répondre.
Tu as raison, j'ai mal formulé. Je t'explique:
En fait j'ai un menu dynamique avec des sous-menu de la forme suivante avec le champ in_form en booléan (1 si la catégorie du menu est bien dans le formulaire donc immobilier, vente..., ET 0 si la catégorie du menu n'est pas dans le formulaire donc Accueil et contact):

Code : Tout sélectionner

id id_parent nom_fr nom_en in_form 1 0 Accueil ... 0 2 0 Immobilier ... 1 201 2 Vente de Maisons ... 1 202 2 Location de Maisons ... 1 203 2 Vente d Appartements ... 1 204 2 Location d Appartements ... 1 205 2 Bureaux ... 1 206 2 Terrains ... 1 3 0 Véhicules ... 1 301 3 Voitures ... 1 301 3 Motos ... 1 302 3 Accessoires ... 1 ... 4 0 Multimedia ... 1 401 4 Téléphones ... 1 402 4 Télévisions ... 1 ... 5 0 ... ... 1 9 0 Contact 0
Mon objectif c'est qu'en cliquant sur moto dans le sous menu, toutes les annonces de la sous catégorie motos s'affichent, ou en cliquant sur un menu donné (ex: véhicules, donc les motos, voitures... s'affichent).

En php voici le lien qui renvoie vers la page où doit s'afficher la catégorie de l'annonce choisie (en récupérant l'id), soit en cliquant sur le menu ou sous-menu:

Code : Tout sélectionner

echo "<li class='menu'><a href= 'affichage.php?id={$menu['id']}'>{$menu['nom']}</a>";

Code : Tout sélectionner

echo "<li class='submenu'><a href= 'affichage.php?id={$sous_menu['id']}'>{$sous_menu['nom']} </a></li>";
Donc en dessous, je récupère l'id:

Code : Tout sélectionner

<?php if(isset($_GET['id'])){ $id_cat = !empty($_GET['id']) ? trim($_GET['id']) : null; $anouncement = affichageAnnonce($id_cat); foreach ($anouncement as $a) { echo '<div class="annoncepubs">'; $images = !empty($a['images']) ? $a['images'] : ['/no_image.png']; // array if (!empty($images)) { //boucle sur les images echo'<div class="container">'; echo ' <div class="slider" >'; foreach ($images as $img) { echo '<img class ="active" style="width:90px; height:90px;" src="' . $img . '">'; } echo "</div>"; // fin div slider . echo '<div class="cont-btn" >'; echo ' <div class="btn-nav left" > <'; echo " </div>"; echo ' <div class="btn-nav right" > >'; echo " </div>"; echo "</div>"; echo "</div>"; // fin div container } echo "<span class='category'>" . $a['CATEGORIE'] . "</span>"; echo "<span class='title'>" . $a['titre'] . "</span>"; echo "<span class='comment'>" . $a['description'] . "</span>"; echo "<span class='price'>" . $a['prix'] . "</span>"; echo "<span class='date'>" . $a['created_date'] . "</span>"; echo "</div>"; // fin div annoncepubs } } ?>
Là où j'ai du mal c'est avec mes fonctions, je ne sais pas ce qui manque:

Code : Tout sélectionner

function getAnnonceCategorie($id_cat){ global $bdd; $sql_lang = (!empty(($_SESSION['lang']) && in_array($_SESSION['lang'], ['fr','en','es']) ))? $_SESSION['lang'] : 'fr'; $sql = ' SELECT A.* ,C.nom_'.$sql_lang.' AS CATEGORIE ,V.ville_'.$sql_lang.' AS VILLE FROM annonces A LEFT JOIN categories C ON C.id = A.id_categorie LEFT JOIN villes V ON V.id = A.id_ville WHERE A.id_categorie = :id_cat ORDER BY A.created_date DESC'; try { $req = $bdd->prepare($sql); $req->execute( array('id_cat'=>$id_cat) ); $res = $req->fetchAll(PDO::FETCH_ASSOC); var_dump($res); } catch (Exception $e) { echo "Erreur dans la requête " . $sql; } // le temps des tests pour voir le résultat return $res; } function getPhotosAnnonces($id_cat){ global $bdd; $sql = 'SELECT id_annonce,filepath as IMG FROM images_annonces WHERE id_annonce= :id_cat'; try { $req = $bdd->prepare($sql); $req->execute( array(':id_cat'=>$id_cat) ); $res = $req->fetchAll(PDO::FETCH_GROUP); var_dump($res); } catch (Exception $e) { echo "Erreur dans la requête " . $sql; } // le temps des tests pour voir le résultat return $res; } function affichageAnnonce($id_cat){ global $bdd; $annonces = getAnnonceCategorie($id_cat); $images = getPhotosAnnonces($id_cat); $res = []; foreach ($annonces as $R) { $res[$R['id']] = $R; $imgs = !empty($images[$R['id']]) ? $images[$R['id']] : NULL; if(!empty($imgs)){ foreach($imgs as $I){ $res[$R['id']]['images'][] = !empty($I['IMG']) ? $I['IMG'] : null; } }else{ $res[$R['id']]['images'] = null; } } return $res; }
Modifié en dernier par max303 le 05 janv. 2022, 01:12, modifié 3 fois.

ynx
Mammouth du PHP | 586 Messages

04 janv. 2022, 22:52

Merci pour les détails, c'est un peu plus clair.

Du coup l'affichage des annonces pour chaque catégorie fonctionne correctement ?
Quel est l'objectif en cliquant sur les menus Accueil et Contact ? Tu veux afficher des annonces sur ces pages ?

A mon avis tu ne devrais pas avoir de catégorie Accueil ou Contact, il ne s'agit pas de catégorie d'annonce mais de page.
Au plus simple, tu pourrais supprimer ces catégories et créer les liens en dur dans le menu html (les url de la page accueil ou contact ne sont normalement pas dynamique, "/contact.php" par exemple).

Eléphant du PHP | 65 Messages

04 janv. 2022, 23:53

C'est plus une bonne idée de faire des lien pour Accueil et Contact. Je n'avais pas pensé à ça. Je viens de le faire en ouvrant les balises php et en les refermant.

Code : Tout sélectionner

$menus = getMenu(0); echo '<ul>'; ?> <li class='menu'><a href="accueil.php">Accueil</a> <?php foreach ($menus as $menu) { echo "<li class='menu'><a href= 'affichage.php?id={$menu['id']}'>{$menu['nom']}</a>";
Concernant l'affichage, lorsque je clique sur un menu ou sous-menu donné je tombe sur une page vide. Rien ne s'affiche.

ynx
Mammouth du PHP | 586 Messages

05 janv. 2022, 00:10

Si rien ne s'affiche, c'est qu'il y a surement une erreur php.
Essaye d'afficher les erreurs php ou regarde dans les logs de ton serveur web :
tutoriels/page-blanche-script-php-comme ... 73178.html

Eléphant du PHP | 65 Messages

05 janv. 2022, 00:50

J'ai encore mal formulé. Je tombe sur une page où il y a uniquement mon header et mon footer. La maquette sur laquelle doit apparaitre l'annonce de la catégorie choisie (i.e l'affichage), est vide.
Peux-tu me confirmer que l'erreur n'est pas dans mon code? Ai-je bien écrit mes fonctions et ma page d'affichage? Si non, que faudrait-il que je fasse?

Eléphant du PHP | 65 Messages

05 janv. 2022, 01:33

J'ai modifié le code qui se trouve là haut comme tu peux le voir, l'annonce s'affiche mais sans images. Quand je fais un vardump de la fonction getPhotosAnnonce, ça retourne un tableau vide.

ynx
Mammouth du PHP | 586 Messages

05 janv. 2022, 14:28

Dans ce cas il faut déboguer la fonction getPhotosAnnonce.

La requête sql pour récupérer les images des annonces ne semble pas correcte :
SELECT id_annonce, filepath as IMG FROM images_annonces WHERE id_annonce = :id_cat
-> Ici tu compares l'identifiant de l'annonce id_annonce avec l'identifiant de la catégorie id_cat, la comparaison n'est donc pas correcte puisqu'il s'agit de deux types d'identifiant différent.

Tu pourrais peut-être modifier cette requête comme ceci :
SELECT id_annonce, filepath as IMG FROM images_annonces WHERE id_annonce IN (SELECT id FROM annonces A WHERE A.id_categorie = :id_cat)
-> Ici, dans la sous-requête entre parenthèse, on récupère uniquement les identifiants des annonces de la catégorie choisie, puis on utilise l'opérateur sql IN pour récupérer toutes les images correspondants à ces annonces.

Eléphant du PHP | 65 Messages

05 janv. 2022, 16:15

Ok ça marche, et pour les catégories parents avec id_parent=0, faudrait-il faire une nouvelle requête avec une fonction, ou faudrait changer
le lien?

Code : Tout sélectionner

echo "<li class='menu'><a href= 'affichage.php?id={$menu['id']}'>{$menu['nom']}</a>";
Si nous devons changer le lien, y-a-t-il un moyen de faire

Code : Tout sélectionner

href= 'affichage.php?id_parent=0 && id=
Quelle serait le bon code.
L'objectif c'est lorsqu'on clique sur une des catégories principale, toutes les sous-catégories s'affichent. Ex: je clique sur véhicules, DONC, les motos, les vélos, les voitures... VONT s'afficher.

ynx
Mammouth du PHP | 586 Messages

05 janv. 2022, 17:21

Il ne semble pas nécessaire de changer le lien ou d'ajouter un paramètre id_parent pour les menus des catégories parents.

Pour afficher les annonces des sous-catégories lorsqu'on sélectionne une catégorie parent, il faut modifier la clause WHERE de la requête sql dans la fonction getAnnonceCategorie().
Par exemple, on pourrait modifier cette requête pour sélectionner les annonces dont la catégorie est égale à la catégorie choisie ou les annonces dont la catégorie parent est égale à la catégorie choisie, soit :
WHERE A.id_categorie = :id_cat OR C.id_parent = :id_cat
Puisque tu as fais une jointure avec la table categories, il me semble que cette clause WHERE devrait fonctionner mais c'est aussi fort probable que je me trompe, n'hésites pas à tester pour vérifier que tu obtiens bien les résultats attendus.

Eléphant du PHP | 65 Messages

05 janv. 2022, 20:13

ça marche, mais ça retourne des images vides pour toutes les catégories dont l'id_parent=0.

Quand on vardump la fonction getPhotosAnnonce, on obtient un tableau vide.

Et quand je modifie la fonction getPhotosAnnonce, ça ne marche pas non plus:

Code : Tout sélectionner

function getPhotosAnnonces($id_cat){ global $bdd; $sql = 'SELECT id_annonce,filepath as IMG FROM images_annonces WHERE id_annonce IN (SELECT id FROM annonces A WHERE A.id_categorie = :id_cat ) OR IN (SELECT id_parent FROM categories C WHERE C.id_parent = :id_cat ) ';

ynx
Mammouth du PHP | 586 Messages

05 janv. 2022, 22:40

Tu ne peux pas enchainer deux conditions IN comme ceci :
WHERE id_annonce IN (...) OR IN (...) -- incorrect
Si besoin de faire deux sous-requêtes, on pourrait éventuellement l'écrire comme ceci :
WHERE id_annonce IN (...) OR id_annonce IN (...) -- correct

Dans ton cas, la sous-requête utilisée dans la clause IN de la fonction getPhotosAnnonces() devrait être la même requête que celle utilisée dans la fonction getAnnonceCategorie(), à l'exception de la clause SELECT pour sélectionner seulement l'identifiant dans la sous-requête.
Si par exemple, la requête pour les annonces dans ta fonction getAnnonceCategorie() est :
SELECT A.*, C.nom_fr AS CATEGORIE, V.ville_fr AS VILLE
FROM annonces A
LEFT JOIN categories C ON C.id = A.id_categorie
LEFT JOIN villes V ON V.id = A.id_ville
WHERE A.id_categorie = :id_cat OR id_parent = :id_cat
ORDER BY A.created_date DESC
La requête sql dans la fonction getPhotosAnnonces() pourrait être :
SELECT id_annonce,filepath as IMG
FROM images_annonces
WHERE id_annonce IN (
    SELECT id 
    FROM annonces A
    LEFT JOIN categories C ON C.id = A.id_categorie
    LEFT JOIN villes V ON V.id = A.id_ville
    WHERE A.id_categorie = :id_cat OR id_parent = :id_cat
)
Le ORDER BY dans la sous-requête n'est pas utile.

Dupliquer la première requête en sous-requête dans ta deuxième fonction devrait fonctionner mais sera compliquer à maintenir. Il faudra que tu penses à modifier correctement ta requête aux deux endroits à chaque changement.

Une autre solution serait de changer le paramètre passé à la fonction getPhotosAnnonces($id_cat).

Au lieu de lui passer l'identifiant de la catégorie des annonces, ce qui oblige à répéter la requête pour sélectionner les annonces en fonction de la catégorie, tu pourrais simplement lui passer les identifiants des annonces que tu as déjà récupéré juste avant avec la fonction getAnnonceCategorie().
Un exemple :
// $annonces : la liste des annonces retournée par la fonction getAnnonceCategorie()
// liste de tableau associatif (si PDO::FETCH_ASSOC est utilisé dans getAnnonceCategorie) avec une clé 'id' pour chaque annonce
function getPhotosAnnonces($annonces) {
	global $bdd;
	$sql = 'SELECT id_annonce,filepath as IMG
	FROM images_annonces
	WHERE id_annonce = IN (' . implode(',', array_column($annonces, 'id')) . ')';
	// ... suite de la fonction
	return $res;
}

function affichageAnnonce($id_cat) {
	global $bdd;
	$annonces = getAnnonceCategorie($id_cat);
	$images = getPhotosAnnonces($annonces); // on passe la liste des annonces en paramètre
	// ...	

Eléphant du PHP | 65 Messages

06 janv. 2022, 01:05

Si la dernière option est meilleure et que je n'aurai pas de surprises avec plus tard,, je la choisie, car la première n'a pas marché:

Code : Tout sélectionner

function getPhotosAnnonces($annonces) { global $bdd; $sql = 'SELECT id_annonce,filepath as IMG FROM images_annonces WHERE id_annonce = IN (' . implode(',', array_column($annonces, 'id')) . ')'; try { $req = $bdd->prepare($sql); $req->execute( array('id_cat'=>$id_cat) ); $res = $req->fetchAll(PDO::FETCH_GROUP); var_dump($res); } catch (Exception $e) { echo "Erreur dans la requête " . $sql; } // le temps des tests pour voir le résultat return $res; }
Est-ce que le execute est bon ?

Code : Tout sélectionner

$req->execute( array('id_cat'=>$id_cat) );
.
J'obtiens les erreurs suivantes:
Notice: Undefined variable: id_cat in C:

Notice: Undefined variable: res in C dans