IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Empêcher la multiplication des enregistrements dans une BDD [PHP 7]


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    fais ce que je peux en n'informatique
    Inscrit en
    Janvier 2012
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : fais ce que je peux en n'informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2012
    Messages : 60
    Points : 30
    Points
    30
    Par défaut Empêcher la multiplication des enregistrements dans une BDD
    Bonjour,

    J'ai mis en place un intranet, pour ma société, dans lequel il y a un formulaire "news"

    Chaque utilisateur doit valider la lecture de la news par un bouton "non lu"
    Le bouton passe alors en état "lu" (il devient inactif pour empêcher de le remettre en "non-lu")

    Côté BDD, à chaque fois qu'un utilisateur clique sur ce bouton "non lu", j’insère une donnée dans une table de liaison contenant les champs suivant : news_lu_id, news_membre_id, news_id

    En utilisation normal cela fonctionne. Mais si je clique plusieurs fois sur le bouton "non lu", cela insère plusieurs lignes identique.

    Je me retrouve avec plusieurs fois la même news en lu

    Je suppose qu'il faut faire une vérification dans le code mais je ne sais pas comment m'y prendre pour empêcher l'ajout d'une ligne identique.

    Merci de votre aide

  2. #2
    Expert éminent sénior
    Avatar de ProgElecT
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2004
    Messages
    6 094
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 68
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité
    Secteur : Communication - Médias

    Informations forums :
    Inscription : Décembre 2004
    Messages : 6 094
    Points : 16 606
    Points
    16 606
    Par défaut
    Salut
    Je suppose qu'il faut faire une vérification dans le code mais
    Si tu ne nous mes pas le code ..... comment pourront nous t'aider ?

  3. #3
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 691
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 691
    Points : 20 230
    Points
    20 230
    Par défaut
    il faudrait surout une contrainte sur ta base de données pour empécher tout ajout en double (clés unique). Il ne reste alors plus qu'à gérer l'erreur dans le code si le problème survient.

  4. #4
    Expert éminent
    Avatar de Séb.
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    5 200
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2005
    Messages : 5 200
    Points : 8 425
    Points
    8 425
    Billets dans le blog
    17
    Par défaut
    Utilise un index UNIQUE sur tes 3 colonnes.

    Les doublons seront refusés par la BdD.

  5. #5
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Plusieurs choses me chiffonnent dans ta description. Déjà pourquoi peut-on cliquer plusieurs fois sur ce bouton "non-lu"? Ce n'est pas normal. Avant de présenter ce bouton comme cliquable, il devrait y avoir une vérification dans la base de données pour l'utilisateur courant (a-t-il oui ou non déjà lu cette news).
    Deuxième chose, tu peux/dois agir au niveau de ta base de données. Tu as une table pour faire la liaison entre les membres et les news, trés bien, appelons la, disons t_news_member, tu as créé une colonne id_news_lu pour faire une clef primaire j'imagine, mais ce n'est pas la peine, car tu peux trés bien définir une clef primaire sur deux colonnes, et l'id de la news avec l'id du membre peuvent trés bien remplir ce rôle. Donc si tu fais ça, il sera impossible de rentrer la même news pour le même membre plusieurs fois dans cette table (puisqu'une clef primaire est unique).
    La table t_news_member devrait ressembler à ça:
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    CREATE TABLE t_news_member(
        fk_nws_id INT NOT NULL,
        fk_mbr_id INT NOT NULL,
     
        PRIMARY KEY (fk_nws_id, fk_mbr_id),
     
        FOREIGN KEY (fk_nws_id) REFERENCES t_news(nws_id),
        FOREIGN KEY (fk_mbr_id) REFERENCES t_member(mbr_id),
    ) ENGINE=InnoDB;

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    fais ce que je peux en n'informatique
    Inscrit en
    Janvier 2012
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : fais ce que je peux en n'informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2012
    Messages : 60
    Points : 30
    Points
    30
    Par défaut
    Bonjour à tous et merci pour vos suggestions et questions


    Voici le code du formulaire pour une news qui n'a jamais été lu.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    					$client_news_jamais_lu=$db->prepare ('SELECT * FROM article_news
    					WHERE (news_id) NOT IN (SELECT news_id FROM x_membre_client_news_lu WHERE x_membre_client_news_lu.membre_id =:id)
    					AND article_news.client_id = :client');
    					$client_news_jamais_lu->bindValue(':client',$client,PDO::PARAM_INT);	
    					$client_news_jamais_lu->bindValue(':id',$id,PDO::PARAM_INT);
    					$client_news_jamais_lu->execute();
    					if ($client_news_jamais_lu->rowCount()>0)
    					{	
    						while ($donnees=$client_news_jamais_lu->fetch())
    						{
    							echo'<table><tr><th align="left" width="670px"><div class="pastille">'.$donnees['news_id'].'</div> &nbsp * '.$donnees['news_titre'].'</th><th width="180px" height="30px" >'.$donnees['news_date'].'</th><td class="vide" rowspan="2" style="padding-top:20px; padding-left:15px"><label class="switch"><input type="checkbox" value="./article.php?action=news-jamais-lu&f='.stripslashes(htmlspecialchars($donnees['categorie_id'])).'&c='.stripslashes(htmlspecialchars($donnees['client_id'])).'&p='.stripslashes(htmlspecialchars($id)).'&n='.stripslashes(htmlspecialchars($donnees['news_id'])).'  " name="checked" onClick="if (this.checked){  window.location = this.value; }"><span class="slider round"></span></label></td></tr>';
    							echo'<tr><td colspan="2">'.code(nl2br(stripslashes(htmlspecialchars($donnees['news_information'])))).'<br /><br /></td></tr></table><br />';					
    						}
    					}


    Je ne donne pas la possibilité de mettre la news à non lu, grâce à l'option checked disabled="disabled"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    					$client_news_lu=$db->prepare ('SELECT * FROM article_news
    					RIGHT JOIN x_membre_client_news_lu ON article_news.news_id = x_membre_client_news_lu.news_id
    					WHERE x_membre_client_news_lu.client_id = :client AND x_membre_client_news_lu.news_lu = 1 AND x_membre_client_news_lu.membre_id = :id
    					ORDER BY x_membre_client_news_lu.news_id ASC');
    					$client_news_lu->bindValue(':client',$client,PDO::PARAM_INT);	
    					$client_news_lu->bindValue(':id',$id,PDO::PARAM_INT);	
    					$client_news_lu->execute();
    					if ($client_news_lu->rowCount()>0)
    					{	
    						while ($donnees=$client_news_lu->fetch())
    						{
    							echo'<table><tr><th align="left" width="670px"><div class="pastille">'.$donnees['news_id'].'</div> &nbsp * '.$donnees['news_titre'].'</th><th width="180px" height="30px" >'.$donnees['news_date'].'</th><td class="vide" rowspan="2" style="padding-top:20px; padding-left:15px">'; if ($donnees['news_lu'] == 1) { echo'<label class="switch"><input type="checkbox" checked disabled="disabled" ><span class="slider round"></span></label>';} echo'</td></tr>';				
    							echo '<tr><td colspan="2">'.code(nl2br(stripslashes(htmlspecialchars($donnees['news_information'])))).'<br /><br /></td></tr></table><br />';					
    						}
    					}




    voici la requête d’insertion

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    case "news-jamais-lu":
    	$fiche = (isset($_GET['f']))?stripslashes(htmlspecialchars($_GET['f'])):'';
    	$unique = (isset($_GET['u']))?stripslashes(htmlspecialchars($_GET['u'])):'';
    	$client = (isset($_GET['c']))?stripslashes(htmlspecialchars($_GET['c'])):'';
    	//$id
    	$news = (isset($_GET['n']))?stripslashes(htmlspecialchars($_GET['n'])):'';
    	$lu = 1;
     
    		$query=$db->prepare('INSERT INTO x_membre_client_news_lu
    		(membre_id, client_id, news_id, news_lu)
    		VALUES (:id, :client, :news, :lu)');
     
    		$query->bindValue(':id', $id, PDO::PARAM_INT);
    		$query->bindValue(':client', $client, PDO::PARAM_INT);
    		$query->bindValue(':news', $news, PDO::PARAM_INT);
    		$query->bindValue(':lu', $lu, PDO::PARAM_INT);
     
            $query->execute();
            $query->CloseCursor();
     
    	 echo'<meta http-equiv="refresh" content="0;url=./article.php?f='.stripslashes(htmlspecialchars($fiche)).'&c='.stripslashes(htmlspecialchars($client)).'">';  
     
     
    break;


    Effectivement, j'ai créé un champs id_news_lu pour avoir une clé primaire. Grâce à vos explications, je me rends compte qu'il sert à rien.
    Je préfère donc me protéger des doublons directement dans la table.

    J'ai remplacé le checkbox par un bouton et ensuite par une image, mais si on est joueur, on a le temps de cliquer plusieurs fois sur ce bouton avant que le navigateur ne réagisse, et du coup, il mémorise toutes les actions et m'insert plusieurs lignes.



    Le petit problème, et que l'intranet est déjà en ligne, je ne peux donc pas créer de nouveau la table, et à vrai dire, j'ai créé la BDD via phpMyAdmin sur le serveur de développement depuis lequel j'ai exporté le fichier sql pour l'importer dans la BDD de production. Mais je ne connais pas bien les commande via Mariadb

    Comment je peux mettre à jour les caractéristiques des champs ?

    Table : x_membre_client_news_lu
    Champ 1 : membre_client_news_id (clé primaire)
    Champ 2 : membre_id
    Champ 3 : client_id
    Champ 4 : news_id
    Champ 5 : news_lu


    Merci

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    fais ce que je peux en n'informatique
    Inscrit en
    Janvier 2012
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : fais ce que je peux en n'informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2012
    Messages : 60
    Points : 30
    Points
    30
    Par défaut
    Re,

    J'ai trouvé, j'ai supprimé le Champ1

    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE x_membre_client_news_lu DROP COLUMN membre_client_news_id;

    Puis mis les clés primaire
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    ALTER TABLE `x_membre_client_news_lu`   ADD PRIMARY KEY (`membre_id`,`news_id`,`client_id`);

    Du coup, nickel, même en étant très joueur, il n'y a plus de doublon

  8. #8
    Expert éminent Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 888
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 888
    Points : 6 632
    Points
    6 632
    Par défaut
    Content que tu ais pu résoudre ton problème. Celà dit, je ne vois pas trop ce que représente précisément 'client' et 'membre' donc difficile de t'en dire plus. Néanmoins, je t'invite à prendre le temps de bien concevoir ta base de données (il y a tout une section sur le forum et des tutoriels qui y sont dédiés), ce qui t'évitera bien des galères par la suite. Le fait qu'elle soit déjà "en production" ne doit pas être un frein, rien ne t'empèche de récupérer les données pour les placer dans une base correctement conçue.

  9. #9
    Nouveau membre du Club
    Homme Profil pro
    fais ce que je peux en n'informatique
    Inscrit en
    Janvier 2012
    Messages
    60
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : fais ce que je peux en n'informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2012
    Messages : 60
    Points : 30
    Points
    30
    Par défaut
    Cette table (x_membre_client_news_lu) permet de savoir qui a lu telle ou telle news de tel ou tel client.

    Elle récupère les champs clé primaire de chacune des tables suivantes :

    - Membres (membre_id)
    - Clients (client_id)
    - News (news_id)

    Après réflexion, le champs client_id pourrait être supprimé puisque chaque news (clé primaire news_id) concerne un unique client.

    J'ai étudié la méthode merise il y a plus de 20 ans, j'ai quelques peu oublié car je n'ai pas trop pratiqué. ça fonctionne mais j'ai en projet d'améliorer ma BDD et mon code.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Meilleure méthode pour enregistrer des données dans une BDD via Javascript
    Par Say hello dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 01/02/2016, 00h09
  2. Pb lors de l'enregistrement des sessions dans une BDD
    Par tomcoch dans le forum Langage
    Réponses: 2
    Dernier message: 17/04/2007, 10h14

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo