PHP PDO : envoyer une requête de mise-à-jour automatique avec GROUP_CONCAT

Résolu/Fermé
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021 - Modifié le 19 févr. 2021 à 15:10
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021 - 21 févr. 2021 à 14:06
Bonjour à tous,
J'ai créé une fonction qui permet d'obtenir les données d'une table (des menus dans l'exemple) et je voudrais lancer une mise-à-jour juste avant d'exécuter la fonction, afin d'obtenir les valeurs actuelles, en évitant de passer par phpMyAdmin pour effectuer la mise-à-jour.
J'ai une requête UPDATE qui fonctionne comme ça:
Il s'agit d'obtenir les libellés des produits de la table produits dont le champ 'menu' est identique (égal à 1, ou 2, ou 3, ou 4 etc.) afin de les concaténer dans le champ 'descriptif_menu' selon le champ 'menu' des lignes de ma table menus.
UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = :menu GROUP BY menu) WHERE menu = :menu;

Et je dois la réitérer pour chaque valeur
:menu
; donc 3 requêtes pour 3 menus ou 5 requêtes pour 5 menus.
Je voudrais automatiser cette requête pour ne pas limiter le nombre de menus possibles.
J'ai donc tenté ça :
require connexion_bdd.inc;
try{
 $menu = 1++;
 $sql_update = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = $menu GROUP BY menu) WHERE menu = $menu";
 $requete = $bdd->prepare($sql_update);
 $requete->execute();
} catch (PDOException $e) {
 echo 'Erreur : ',$e->getMessage(),'<br />';
 die();
}

..et ça marche pas !!
J'ai tenté avec
$menu = '1++';
, sans résultat.
J'ai tenté avec
$sql_update = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = :menu GROUP BY menu) WHERE menu = :menu";
$requete->bindParam(':menu',$menu);
avec les mêmes essais du
$menu=1++;
et aucun résultat.
Je pense qu'il y a moyen de faire varier ce
$menu
pour qu'il soit opérant entre 1 et N (entier positif) mais je ne trouve pas la bonne syntaxe, si c'est une question de syntaxe...

Est-ce que ça parle à l'un de vous ?
Merci de votre lecture ;p
A voir également:

4 réponses

jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024 4 719
19 févr. 2021 à 15:27
Bonjour,

$menu = 1++; ... ça revient à écrire $menu = 2;

Où est initialisée ta variable menu ?
Sachant que pour l'incrémenter.. il suffit de faire $menu++;

Mais si je comprend bien ce que tu veux faire .. c'est une boucle de 1 à N ... ?
Donc.. pour ça..il faut faire une boucle...
for($menu=1; $menu<10; $menu++){
   //ici $menu prendra les valeurs de 1 à 9 

}


Par contre, quel est l'intéret de stocker dans ton champ descriptif_menu la concaténation... que tu peux, de toutes façons, obtenir lorsque tu fais ta requête SELECT pour afficher les infos de tes menus ?
A part dupliquer les données en bdd ( ce qui est source d'erreur).. il n'y a aucune utilité...



0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021
19 févr. 2021 à 17:05
Bonsoir jordane45,
Merci de ta réponse, le but est la mise-à-jour avant la requête select qui affiche simplement (via une fonction) les lignes de la table menus :
function GetMenus(){
require ('cnxbdd.inc'); //connexion bdd
try{
	$sql = "SELECT * FROM menus ORDER BY menu";
	$datas = $bdd->query($sql);
	foreach ($datas as $row) {
	$label = htmlspecialchars($row['label_menu']);
	$descriptif = htmlspecialchars($row['descriptif_menu']);
	$prix = $row['prix_menu'];
	$str1 = " <h3>";
	$str2 = "</h3>";
	$str3 = "<p>Composé par les plats : ";
	$str4 = ", est au prix de <em>";
	$str5 = " €</em>.</p><br />";
	echo $str1 . $label . $str2 . $str3 . $descriptif . $str4 . $prix . $str5;
	}
} catch (PDOException $e) {
	echo $e->getMessage();
	}
require ('oxied.inc'); //fermeture de la connexion et vidage de la requête
}

Ce qui donne :
<p> </p>
 <h3>Menu de la semaine</h3>
<p>Composé par les plats : Potage de saison, Poulet à la Bière, est au prix de <em>9.90 €</em>.</p>
<br />
 <h3>Menu du samedi</h3>
<p>Composé par les plats : Velouté au Fromage, Canard sauce aux Cèpes, est au prix de <em>11.50 €</em>.</p>
<br />
 <h3>Menu du dimanche</h3>
<p>Composé par les plats : Soupe Galloise (Cawl), Aligot & Saucisse, est au prix de <em>12.50 €</em>.</p>
<br />
<p> </p>

Mais lorsqu'un nouveau produit intègre un menu, ou qu'un nouveau menu est créé, je veux mettre-à- jour le champ "descriptif_menu" qui passe par la requête :
UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = :menu GROUP BY menu) WHERE menu = :menu

avec le code php suivant :
try{
	$sql2 = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = 1 GROUP BY menu) WHERE menu = 1";
	$requete2 = $bdd->prepare($sql2);
	$requete2->execute();
	$sql3 = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = 2 GROUP BY menu) WHERE menu = 2";
	$requete3 = $bdd->prepare($sql3);
	$requete3->execute();
	$sql4 = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = 3 GROUP BY menu) WHERE menu = 3";
	$requete4 = $bdd->prepare($sql4);
	$requete4->execute();
} catch (PDOException $e) {
	echo 'Erreur : ',$e->getMessage(),'<br />';
	die();
}

Car il y a 3 menus différents.
Donc si j'ai un 4ème menu de créé, ou même un cinquième, etc., je veux pouvoir n'envoyer qu'une seule requête, en faisant varier seulement
:menu
ou
$menu
. Et là, je n'arrive pas à trouver la syntaxe.
0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021
19 févr. 2021 à 17:13
Du coup j'ai modifié mon code avec ton éclairage :
try{
	for($menu=1; $menu<10; $menu++) {
	$sqlu = "UPDATE menus SET descriptif_menu = (SELECT GROUP_CONCAT(label SEPARATOR ', ') FROM produits WHERE menu = $menu GROUP BY menu) WHERE menu = $menu";
	$requete = $bdd->prepare($sqlu);
	$requete->execute(); }
} catch (PDOException $e) {
	echo 'Erreur : ',$e->getMessage(),'<br />';
	die();
}

Et ça fonctionne exactement comme je le voulais !
=)
Merci beaucoup, encore une fois !!!
0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021
19 févr. 2021 à 17:27
Je comprends bien que je pourrais intégrer le descriptif_menu lors de l'extraction des champs des menus en couplant les deux requêtes SELECT, mais ça ne mettrait pas à jour la table des menus. Or, c'est cette mise-à-jour que je recherche. Sinon, effectivement, je ne vois pas vraiment l'utilité d'une table menus...

En tous cas, je te remercie bien, jordane45, pour ta célérité, ta compréhension et la justesse de tes conseils !
0
jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024 4 719
19 févr. 2021 à 18:35
On a déjà eu cette discussion... et j'insiste ....

Ton schéma de BDD n'est pas bon !

Tu devrais avoir un truc de ce genre


(en ajoutant d'autres champs si besoin.. )

Mais donc
Une table MENUS .. qui ne contient rien de plus que la liste des menus ( que le nom du menu et son prix )
Une table PLATS : qui contient l la liste des différents plats possibles ( dès fois qu'un jour tu fasses (ou ton pote) de la vente "à la carte" )
Une table de liaison qui permet d'assigner à un menu.. des plats.. (un même produit pouvant se trouver dans différents menus )

Ensuite, pour récupérer la liste des plats d'un menu, il suffit d'utiliser les JOINTURES sur les requêtes SQL.

Voila.. c'est un fonctionnement "normal" contrairement à ce que tu fais...
0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021
19 févr. 2021 à 20:32
J'ai bien compris !
J'ai choisi la solution d'une table menus avec un champ de description, puisque si (effectivement) mon pote est intéressé par faire lui-même un descriptif de son menu (dans le cas ou il trouverait une utilité à créer des menus dans son activité), la fonction
GetMenus()
n'aura pas besoin d'être changée, simplement tronquer le code en "sortant" les requêtes de mise-à-jour (pourquoi pas via la gestion d'un
include
?).
Si je pars de ton merise de la bdd, j'imagine devoir aussi créer plusieurs
include
afin de gérer ces descriptifs, voire c'est impossible en partant de cette architecture ?
Enfin bon !
On en apprends tous les jours n'est-ce pas ?
Je te souhaite une bonne soirée.
0
jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024 4 719
19 févr. 2021 à 20:56
Il suffit de mettre un champ descriptif dans la table Menu que ton pote pourra remplir avec du texte si il le souhaites.

Et si il ne veut plus afficher la liste des produits, là, il suffit en effet de mettre cette partie dans un include et donc de ne plus l'inclure si il ne les veut plus....

Ce qu'il faut, c'est éviter d'avoir des données redondantes dans les tables....
0
jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024 4 719 > jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024
19 févr. 2021 à 21:02
Avec la structure que je t'ai donné :

La requête deviendrait un truc du genre
SELECT M.*
             ,GROUP_CONCAT(P.nom_du_plat SEPARATOR ', ') as LISTE_PLATS
FROM  menus_plats MP
LEFT JOIN menus M ON M.id = MP.id_menu
LEFT JOIN plats P  ON P.id = MP.id_plats
WHERE MP.id_menu = 1
GROUP BY MP.id_menu

A noter que le WHERE n'est pas obligatoire .. il ne sert que si tu veux afficher les infos que d'un seul menu.

Et donc.. en une seule requête.. tu as toutes les infos de ton menu + la liste des plats concaténés ...

Teste cette requête directement en BDD dans phpmyadmin .. tu verras ce que ça donne...
0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021 > jordane45 Messages postés 38358 Date d'inscription mercredi 22 octobre 2003 Statut Modérateur Dernière intervention 28 décembre 2024
Modifié le 21 févr. 2021 à 14:45
Bonjour !
J'ai déjà une table menus avec un champ descriptif_menu que je peux modifier directement par phpMyAdmin, et une table produits, dont la primary key (unique) est '
reference' int(5) NOT NULL AUTO_INCREMENT
.
J'ai essayé ça :
CREATE TABLE `menus_produits` (
  `menu` int(5) NOT NULL AUTO_INCREMENT,
  `descriptif_menu` varchar(300) NOT NULL,
  `reference` varchar(300) NOT NULL,
  PRIMARY KEY (`menu`)
) ENGINE=MyISAM AUTO_INCREMENT=101 DEFAULT CHARSET=utf8;

INSERT INTO `menus_produits` VALUES (1,'Menu de fin de semaine',''),(2,'Menu du samedi',''),(3,'Menu du dimanche','');

SELECT menus.* ,GROUP_CONCAT(produits.label SEPARATOR ', ') as labels
FROM menus_produits
LEFT JOIN menus ON menus.menu = menus_produits.menu
LEFT JOIN produits ON produits.reference = menus_produits.reference
WHERE menus_produits.menu = 1
GROUP BY menus_produits.menu;

J'avais essayé en laissant la 'reference' à
int(5)
comme dans la table produits mais il fallait que je rentre l'insert :
INSERT INTO `menus_produits` VALUES (1,'Menu de fin de semaine',NULL),(2,'Menu du samedi',NULL),(3,'Menu du dimanche',NULL)
pour que ça ne fasse pas d'erreur.

J'ai donc ce retour :
+------+------------------------+---------------------------------------+-----------+--------+
| menu | label_menu             | descriptif_menu                       | prix_menu | labels |
+------+------------------------+---------------------------------------+-----------+--------+
|    1 | Menu de fin de semaine | Potage de saison, Poulet à la Bière   |      9.90 | NULL   |
+------+------------------------+---------------------------------------+-----------+--------+
1 row in set (0.001 sec)

J'ai essayé en remplaçant le second LEFT JOIN par RIGHT JOIN mais ça me donne rien de mieux. Une erreur traîne et je ne sais pas où ?
0
Recoh Messages postés 36 Date d'inscription dimanche 19 juillet 2020 Statut Membre Dernière intervention 2 mars 2021
19 févr. 2021 à 21:25
Je pense comprendre la limite de mon merise, lorsqu'il s'agit de plusieurs menus qui peuvent contenir des mêmes produits.
En y réfléchissant, j'imagine une chaîne de charactère à la place de l'entier pour chaque plat, décodée par php, plutôt que plusieurs colonnes "menu1", "menu2", "menu3", encore que...
Et il doit bien exister une syntaxe, ou un genre de fonction, sql, qui "fasse le tri" ?...
Du coup, c'est plutôt une méthode d'apprentissage à la "Rousseau" qu'une méthode à la "Voltaire" !
:)
0