[RESOLU] Faire une requête avec plusieurs id dans un champ

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : [RESOLU] Faire une requête avec plusieurs id dans un champ

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 22 oct. 2015, 13:39

C'est parfait ça fonctionne merci !
Je passe le sujet en résolu, encore merci Ryle. ;)

Re: Faire une requête avec plusieurs id dans un champ

par Ryle » 22 oct. 2015, 13:07

A tous les coups c'est dans la construction de la valeur reçue dans $_POST['sondage_reponses']. Il doit y avoir une virgule en trop au début ou à la fin (sans doute en prévision de l'ajout d'un nouvel id), ce qui fait que l'explode génère une entrée vide dans le tableau.

Pour éviter cela, le mieux serait de revoir la façon dont les id news sont sélectionnés et envoyés, mais sinon au plus simple, il suffit juste de contrôler la valeur avant de faire l'insertion en base et de ne rien faire si celle-ci est vide ou à 0 :
foreach ($tabNews as $idNews) {
      if (!empty($idNews)) {
        $sql = "INSERT INTO sondage_news VALUE('','" . $id_data . "', '" . $idNews . "', '" . $_SESSION['id'] . "')";
        $bdd->query($sql);
      }
    }

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 22 oct. 2015, 12:18

Parfait ça fonctionne merci Ryle !
Juste un soucis quand ça insert dans la table, il y a une ligne qui insert un id 0 à chaque fois. D'où cela peut-il venir ?

Re: Faire une requête avec plusieurs id dans un champ

par Ryle » 22 oct. 2015, 10:58

Dans tous les cas il te faut générer une requête d'insertion par ID news. Le fait qu'elles soient préparées ou non ne changera rien à l'affaire, c'est juste que c'est dans ce type de situation (exécution de plusieurs requêtes de structures identiques) que les requêtes préparées sont le plus efficaces.

Pour pouvoir générer autant d'insert que d'id news, il faut juste regarder ce que contient ta variable $_POST['sondage_reponses']. Si aujourd'hui celle-ci est inséré en l'état dans ta table, je suppose qu'elle contient la liste des id sélectionné sous la forme " id1, id2, id3 "

Il suffit donc d'exploiter ce format pour lire chacun des id et générer les requêtes. Pour cela on commence par transformer la chaine en tableau en éclatant la chaine par rapport au séparateur "virgule" et ensuite on parcours ce tableau d'id pour générer les insert :
$id_data = $bdd->lastInsertId();

  if (!empty($_POST['sondage_reponses'])) {
    $tabNews = explode(',', $_POST['sondage_reponses']);
    foreach ($tabNews as $idNews) {
      $sql = "INSERT INTO sondage_news VALUE('','" . $id_data . "', '" . $idNews . "', '" . $_SESSION['id'] . "')";
      $bdd->query($sql);
    }
  }

  $sondagecree=1;
  ...

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 21 oct. 2015, 16:23

Merci pour ces conseils Ryle.

En fait, ce n'est pas un tableau vu qu'avant ça ajoutait tous les id dans un même champ dans la table.
Pour expliquer clairement la situation, il s'agit de créer un sondage dans lequel on met une question et aussi dans lequel on sélectionne les news par autocompletion.
J'ai séparé le tout en 2 tables, la table sondages dans laquelle il y a l'id, la question, l'id du posteur, la date et une autre table sondage_news dans laquelle je stock l'id, id_sondage, reponses, posteur.
Lors de l'envoie du formulaire la première requête est bien effectuée mais dans la seconde il manque l'ajout de l'id des news qu'on a choisis au préalable par le système d'autocomplétion.

Donc je ne vois pas trop comment je pourrais faire pour résoudre ce problème.

Avec une requête préparée ça résoudrait ce problème tout seul ? C'est à dire que ça créera automatiquement des lignes dans la table pour chaque id de news envoyé par le formulaire ?

Re: Faire une requête avec plusieurs id dans un champ

par Ryle » 21 oct. 2015, 15:57

SI tu as plusieurs id de news dans $_POST['sondage_reponses'], il te faut effectivement effectuer une boucle et réaliser un INSERT pour chaque id.

Si $_POST['sondage_reponses'] est un tableau contenant chacun des id, tu peux utiliser un foreach :
foreach ($_POST['sondage_reponses'] as $idReponse) {
  $bdd->query("INSERT INTO sondage_news VALUE('','".$id_data."','".$idReponse."','".$_SESSION['id']."')");
}
Si tu utilises pdo tu peux également utiliser les requêtes préparées qui sont idéales dans ce cas (exécution de la même requête plusieurs fois avec des valeurs différentes)

S'il ne s'agit pas d'un tableau d'id, il faut regarder sous quelle forme tu les reçois et adapter le traitement pour faire ta boucle (en utilisant par exemple explode() etc.)

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 21 oct. 2015, 13:14

Du coup j'ai essayé de séparer en 2 tables différentes mais je rencontre un problème lors de l'insertion des id en plusieurs lignes.
En réalité ça n'insert rien du tout pour les id des multiples news dans le champ reponse de la table sondage_news.
Je pense que ça vient du fait que ça veut insérer tous les id dans le champ en question sauf que je voudrais une nouvelle ligne à chaque fois.
Voici ma table sondage_news : id(int), id_sondage (int), reponse (int), posteur (int)
Et ma table : sondages : id, intitule, membre, date
Voici mon code :
if (isset($_POST['sondage_reponses']) && $_POST['sondage_reponses']!='' && isset($_POST['sondage_titre']) && $_POST['sondage_titre']!='') {
	$bdd->query("INSERT INTO sondages VALUE('','".$_POST['sondage_titre']."','','".$_SESSION['id']."','".date('d/m/Y',time())."')");
	$id_data = $bdd->lastInsertId();
	$bdd->query("INSERT INTO sondage_news VALUE('','".$id_data."','".$_POST['sondage_reponses']."','".$_SESSION['id']."')");
	$sondagecree=1;
}
if ($_GET['bdel']==1) { unlink(__FILE__); } 
if ($_SESSION['id']>0) {
?>
            	<div class="container_12">
                	<div class="wrapper pad-top1">
                        	<h2 class="h2-bot" style="text-align:center;"><a>Sondage</a></h2>
                            <div class="wrapper" align="center">
							<? if ($sondagecree==1) { echo '<div style="color:#00B300;">Le sondage a correctement été crée.</div><br><br>'; } ?>
								<form action="" method="POST"><input type="hidden" name="sondage_reponses">
								<div style="width:400px">
								<span style="float:left;">Intitulé :</span> <input type="text" name="sondage_titre" style="float:right"><br><br>
								<span style="float:left;">Réponses :</span> <input type="text" style="float:right" placeholder="Ecrivez le nom d'une news" id="sondageNews"><br><br><br><div id="results_sondage"></div><br><br><div id="results_sondage_c"></div><br><br><input type="submit" value="Créer le sondage">
								</div>
								</form>
							</div>
                <div class="wrapper">
                	<div class="grid_12">
                    	<div class="border1 border1-top"></div>
                    </div>
                </div>
            </div>
<?
}
else { echo '<br><br><div align="center">Connectez vous pour accéder à cette partie.</div>'; }
?>

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 21 oct. 2015, 12:13

Merci pour ton aide Ryle.
Ce qui me parait bizarre c'est que c'est une personne qui est développeur dans la vie qui m'a conseillé de faire comme ça.

Je vais quand même tenter de modifier ça pour le faire en jointure car je sens que ça va devenir compliqué sinon. ^^

Surtout que je voudrais utiliser like pour afficher le titre des news dont l'id est enregistré dans le champ avec les multiples id...

Re: Faire une requête avec plusieurs id dans un champ

par Ryle » 21 oct. 2015, 10:37

Bonjour,

Alors effectivement, tu peux utiliser le like (c'est d'ailleurs la seule solution dans ton cas), mais je rejoint Moogli et te recommande fortement (très fortement... TRES TRES FORTEMENT) de revoir la structure de la base de données :)

En effet, si tous les ids sont dans un même champ texte, outre le fait que celui-ci est limité en taille et que le nombre d'ids qu'il pourra contenir sera également limité (même si dans le principe y en aura probablement pas des milliers), tu vas également rencontrer des problèmes pour aller retrouver une valeur.
Certes le LIKE te permet de faire une condition du genre " WHERE id_proposition_sondage LIKE '%50%' " pour retrouver les sondages contenant l'id 50. Le problème étant qu'il va également te retourner ceux contenant l'id 150, 250, 350, 450, 501, 502, ... que tu ne veux pas.
Il faudrait donc rechercher " WHERE id_proposition_sondage LIKE '% 50,%' " sauf que si le 50 est à la fin, il n'y a pas de virgule après et il ne sera pas retrouvé.
La requête devrait donc devenir " WHERE CONCAT(' ', id_proposition_sondage, ',') LIKE '% 50, %' " pour être sur qu'on a bien que le 50 et pas des 150 ou des 501 ...

Tu devines aisément que les ressources allouées pour faire une concaténation de la valeur de chacun des enregistrements, puis un LIKE sont largement supérieur à un simple = dans une jointure :)
Et côté stockage, un champ de type texte (qui plus est dans lequel tu es obligé de rajouter des séparateurs) occupe forcément plus de place qu'un champ de type numérique.

Bref, je ne sais pas qui t'as laissé entendre que cette solution serait plus optimisée et consommerait moins, mais je lui suggère fortement de revoir les bases des bases de données... :)

Re: Faire une requête avec plusieurs id dans un champ

par Larker » 20 oct. 2015, 21:12

Salut Moogli,

Tout d'abord merci de ton aide.
Dans mon cas il s'agit de faire un sondage pour savoir quelles news sont les mieux d'après les membres. Donc quand je créé le sondage j'ai stocké les proposition de réponses (les id de news) directement dans le champ réponse.
Ensuite, on m'a dit que dans mon cas de figure c'était plus optimisé de faire comme ça, que ça consommerait moins.
On m'a dit qu'avec LIKE je pourrais faire ça ?

Re: Faire une requête avec plusieurs id dans un champ

par moogli » 20 oct. 2015, 20:28

salut,

il faudrait :
- un requête qui sélectionnent les infos voulues
- une sous requête qui calcule les id.

Globalement cette façon de faire est à proscrire, c'est un défaut de conception.

Avec un SGBDR (le R pour relationnel) on utilise plusieurs tables et des clefs étrangères pour simplifier la chose.
- une table sondage
- une table proposition (associé à une news ?) : cette remplace le champ contenant les id séparé par des virugles.
- si j'ai bien compris une table news
exemple de table
create table sondage (
sondeID int not null primary key,
nomsondage varchar(50)
//etc
);
create table news (
newsID int not null primary key,
titreNews varchar(50)
// etc
)
create table sondageNews (
newsID int not null,
sondageID int not null
);
ALTER TABLE sondageNews ADD CONSTRAINT fk_newsID FOREIGN KEY (newsID) REFERENCES news(newsID) ;
ALTER TABLE sondageNews ADD CONSTRAINT fk_sondageID FOREIGN KEY (sondageID) REFERENCES sondage(sondageID);
Si tu veux les sondages associés à la news courante
select * from sondage where sondageID in ( select sondageID from sondageNews where newsID = xxx)
Où xxx est le numéro de la news dont on veux les sondages.

cela permet :
- d'éviter d'avoir des id qui ne correspondent pas avec la réalité (cohérence des données)
- Ajouter / modifier / supprimer facilement sondage pour une news sans risquer de flinguer un autre enregistrement.
- Les tables sondages et news n'ont pas de données qui ne leurs sont pas propre (on par d'entité).

Pour plus d'info sur la modélisation je t'invite à regarde le modèle entité association de la méthode merise.

@+

Faire une requête avec plusieurs id dans un champ

par Larker » 20 oct. 2015, 19:12

Bonjour,

Je souhaiterais savoir comment exploiter plusieurs id qui sont contenus dans un champ dans une table ?
exemple : Champs id_proposition_sondage : 2, 150, 558, 698
Je souhaiterais savoir comment les sélectionner un à un avec une requête.

Est-ce faisable ?

Voici mon code actuel :
<?php
    $stmt = $bdd->prepare("SELECT S.id, S.intitule, S.reponses, S.date, S.membre, F.titre FROM sondages S, news F WHERE S.reponses=F.id ORDER BY `id` DESC LIMIT 0,6");
    if (!$stmt->execute()) {
        echo 'ERREUR';
        exit; //pas obligatoire
    }
while ($getNews = $stmt->fetch()) { 
?>
<div>
<?=$getNews['titre']; ?>
</div>
<?php } ?>
Le problème c'est que ça me donne uniquement le titre avec le premier id enregistré dans le champ alors que je les voudrais tous.

Merci à ceux qui pourront m'aider.