Eviter les doubles doublons

Petit nouveau ! | 9 Messages

27 mars 2007, 13:38

J'ai actuellement une table simple avec :
id
nom
prenom
date

Mais je n'ai aucun système pour éviter d'avoir nom+prenom en doublon.

J'ai trouver cette ligne de commande mais comment faire pour que cela fonctionne sur 2 valeurs et non sur une seule car j'ai vu qu'on pouvait mettre un SELECT dans un autre SELECT mais j'ai arrive pas :

Code : Tout sélectionner

$test = mysql_query("SELECT * FROM donnees WHERE nom='$nom'"); $verdict = mysql_fetch_array($test, MYSQL_ASSOC); if ($nom == $verdict['donneesnom']) { echo "Cette personne existe déjà dans la base de données<br>"; exit; }
Merci d'avance.
Modifié en dernier par lordbdp le 28 mars 2007, 23:00, modifié 1 fois.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

27 mars 2007, 15:47

Inutile de t'embêter avec une sous requête, il suffit d'ajouter un second paramètre dans ton WHERE :)
$sql = "SELECT count(*) 
  FROM donnees 
  WHERE nom='". $nom "' 
  AND prenom = '". $prenom ."'";
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
AB
ViPHP | 5818 Messages

27 mars 2007, 22:30

Bonjour,

Si besoin, voici le code de Ryle complété avec tes éléments:
$test = "SELECT count(*) 
  FROM donnees 
  WHERE nom='". $nom ."' 
  AND prenom = '". $prenom ."'";

$verdict = mysql_query($test, MYSQL_ASSOC);
$Total_row = mysql_fetch_row($verdict);
$total = $Total_row[0];

if ($total > 0)
{//personne déjà enregistée}
Mais attention car tel quel la requête n'est pas protégée des injections

Petit nouveau ! | 9 Messages

27 mars 2007, 23:03

Merci pour le code manquant.

Comment faire pour se protéger des injections ? (C'est quoi une injection ???)

Merci encore.

ViPHP
AB
ViPHP | 5818 Messages

27 mars 2007, 23:27

Toute l'info dans les exemples de la fonction mysql_real_escape_string()

Selon la doc ta requête devrait ressembler à
$test = sprintf("SELECT count(*) 
  FROM donnees 
  WHERE nom='%s'
  AND prenom ='%s'",mysql_real_escape_string($nom),
mysql_real_escape_string($prenom));
C'est important (pour éviter le piratage) si ce sont les visiteurs qui envoient leur nom et prénom via un formulaire.

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

27 mars 2007, 23:52

Rien à ajouter si ce n'est juste une petite remarque pesonnelle concernant le sprintf... faut pas faire comme les éditeurs à la dreamweaver et l'utiliser pour des requêtes ... avec 2 paramètres c'est supportable (et encore) mais dès qu'il y en aura 5 ou plus, ca va vite devenir illisible. :(
On ne sait plus quelle variable va dans quel champ on perds du temps à vérifier l'ordre, les formats, c'est galère pour en rajouter un ou en enlever un... c'est sincèrement insuportable quand il faut passer derrière ce genre de code, alors qu'une simple concaténation donne le même résultat et est tellement plus simple à maintenir :)
$sql = "SELECT COUNT(*)  
  FROM donnees  
  WHERE nom = '".mysql_real_escape_string($nom)."' 
  AND prenom = '".mysql_real_escape_string($prenom)."'"; 
Il y a surement des fois où c'est utile (personnellement j'en ai pas encore trouvé, entre le cast implicite les fonctions de formatage) mais pitié, pas pour du sql :)


Vala, ca n'apporte rien de plus au sujet, c'était juste mon p'tit coup de trougne du soir ;)
(faudrait d'ailleurs que je pense à l'ajouter au do's and don't sql çuilà :))
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
AB
ViPHP | 5818 Messages

28 mars 2007, 00:19

Salut Ryle,

Ben c'était pas du dreamweaver, c'était simplement le copié collé du premier exemple (1529) de la doc PHP sur mysql_real_escape_string()

Et comme je suis pas un expert, j'ai plutôt tendance à suivre la doc.

Maintenant si tu penses que ça ne sert à rien, ça m'arrangerais plutôt, car comme tu le dis, c'est assez pénible de passer derrière quand il y a beaucoup de paramètres...

Mais alors pourquoi la doc PHP conseille également le formatage dans l'exemple 1531. ça n'apporte strictement rien par rapport à une concaténation? même pas pour se protéger de pirates hyper tordus?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

28 mars 2007, 00:31

ah ben voilà ! tu as trouvé, ca sert dans la doc ! ;)

plus sérieusement, c'était pas du tout après toi ou dreamweaver (encore que pour ce dernier.. ;)) mais justement parce que je comprend pas l'intérêt de cette fonction pour du SQL.

sprintf a pour but de formater une chaine.. alors c'est bien quand tu dois répéter plusieurs fois un élément, ca évite de le retaper à chaque fois (donc un seul endroit ou le modifier le cas échéant) et potentiellement inculquer la notion de type de données (même si ca n'empêche pas de continuer de voir des quotes autour de nombres :x )
Mais pour générer du code sql, franchement, à part respecter la devise "ca a été dur à coder, ca doit être dur à comprendre" je vois vraiment pas :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Petit nouveau ! | 9 Messages

28 mars 2007, 11:36

Donc le code suiavnt serait le bon si j'ai bien compris :

Code : Tout sélectionner

$test = "SELECT count(*) FROM donnees WHERE nom='". $nom ."' AND prenom = '". $prenom ."'"; $verdict = mysql_query($test, MYSQL_ASSOC); $Total_row = mysql_fetch_row($verdict); $total = $Total_row[0]; if ($total > 0) {//personne déjà enregistée} $test = sprintf("SELECT count(*) FROM donnees WHERE nom='%s' AND prenom ='%s'",mysql_real_escape_string($nom), mysql_real_escape_string($prenom));
Je ne rajoute pas un else avant le 2eme $test ?

ViPHP
AB
ViPHP | 5818 Messages

28 mars 2007, 11:53

La requête complète :
$test = sprintf("SELECT count(*) 
  FROM donnees 
  WHERE nom='%s'
  AND prenom ='%s'",mysql_real_escape_string($nom),
mysql_real_escape_string($prenom)); 

$verdict = mysql_query($test, MYSQL_ASSOC);
$Total_row = mysql_fetch_row($verdict);
$total = $Total_row[0];

if ($total > 0)
{//le code que tu exécute si la personne est déjà enregistée
} 
Mais bon, tu devrais aller faire un tour du coté de http://www.phpdebutant.org et faire quelques tutos :wink: sinon tu ne vas pas t'en sortir.

Petit nouveau ! | 9 Messages

28 mars 2007, 22:58

Merci je vais tester. J'en profiterais pour aller jeter un oeil sur le site pour neuneus comme moi , lol.

Merci à tous.

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 13231 Messages

29 mars 2007, 08:09

tu n'est pas "neuneu", juste débutant.

On est tous passé par là ;)
Connaître son ignorance est la meilleure part de la connaissance
Pour un code lisible : n'hésitez pas à sauter des lignes et indenter

twitter - site perso - Github - Zend Certified Engineer

Petit nouveau ! | 9 Messages

29 mars 2007, 18:14

Ben je me prend un message d'erreur pour 2 lignes de code :
mysql_query(): supplied argument is not a valid MySQL-Link resource
pour :

Code : Tout sélectionner

$verdict = mysql_query($test, MYSQL_ASSOC);
mysql_fetch_row(): supplied argument is not a valid MySQL result resource
pour :

Code : Tout sélectionner

$Total_row = mysql_fetch_row($verdict);
:cry: :cry: :cry:

Je vous donne mon code complet si cela peut vous aider :

Code : Tout sélectionner

<title>Petition</title> <style type="text/css"> body { background-color: white; color: black; font-family: Arial, Verdana, serif; font-size: 12px; } input { border: 1px solid; border-color: black; background-color: white; color: black; font-family: Arial, Verdana, serif; font-size: 12px; } table { border-collapse: collapse; } td { border: 1px solid; border-color: black; } </style> <?php // On inclu le fichier de configuration include('config.php'); ?> <form action="<?php echo $PHP_SELF; ?>" method="post"> <center> Nous vous invitons à signer cette pétition, si vous le voulez bien, pour soutenir cette cause : <br /><br /><?php echo $cause; ?> <br /><br /><br /> Prénom : <input type="text" name="prenom"><br /><br />Nom : <input type="text" name="nom"> <br /><br />Date : <?php echo date('d/m/Y'); ?> <br /><br /><input type="submit" name="submit" value="Valider">&nbsp;<input type="reset" name="reset" value="Recommencer"> <br /><br /> </center> </form> <?php echo '<center><table><tr><td><b>Nom</b></td><td><b>Prénom</b></td><td><b>Date de signature</b></td></tr>'; // On se connecte à la base de données mysql_connect("$host", "$login", "$password"); mysql_select_db("$bdd"); // On sécurise les champs $nom = htmlspecialchars($_POST['nom']); $prenom = htmlspecialchars($_POST['prenom']); $date = date('d/m/Y'); $submit = htmlspecialchars($_POST['submit']); // On vérifie que tous les champs sont bien remplis if($submit && empty($nom)) { // Message d'erreur die('<center>Vous devez remplir tous les champs.<br /><br /></center>'); } if($submit && empty($prenom)) { // Message d'erreur die('<center>Vous devez remplir tous les champs.<br /><br /></center>'); } // On vérifie que les champs sont assez longs pour être raisonnables $long1 = strlen($nom); $long2 = strlen($prenom); // Si le nom est trop court (plus petit que 3 caractères) if($submit && $long1 < '3') { // Message d'erreur die('<center>Votre nom doit faire plus de 3 caractères.<br /><br /></center>'); } // Si le prénom est trop court (plus petit que 3 caractères) if($submit && $long2 < '3') { // Message d'erreur die('<center>Votre prénom doit faire plus de 3 caractères.<br /><br /></center>'); } // On évite les doublons dans la base $test = sprintf("SELECT count(*) FROM petitions WHERE nom='%s' AND prenom ='%s'",mysql_real_escape_string($nom), mysql_real_escape_string($prenom)); $verdict = mysql_query($test, MYSQL_ASSOC); $Total_row = mysql_fetch_row($verdict); $total = $Total_row[0]; if ($total > 0) { //Cette personne est déjà enregistée die('<center>Cette personne a déjà signé la pétition.<br /><br /></center>'); } if($submit) { // On enregistre la participation à la pétition mysql_query("INSERT INTO power_petition VALUES('', '" . $nom . "', '" . $prenom . "', '". $date ."')"); } // On sélectionne les résultats $sql = mysql_query('SELECT * FROM power_petition ORDER BY id DESC'); // On compte le nombre de signatures $signs = @mysql_num_rows($sql); while($donnees = @mysql_fetch_array($sql)) { ?> <tr> <td> <?php echo $donnees['nom']; ?> </td> <td> <?php echo $donnees['prenom']; ?> </td> <td> <?php echo $donnees['date']; ?> </td> </tr> <?php } echo '</table></center>'; // On ferme la connexion MYSQL mysql_close(); ?>
Merci encore.

Si vous voulez voir le résultat : http://www.neogame.fr/petitions/index.php

Mammouth du PHP | 693 Messages

30 mars 2007, 08:53

IL faut que tu mette MYSQL_ASSOC comme deuxième argument de mysql_fetch_array() et non de mysql_query().

(IL y a une fonction, mysql_fetch_assoc($requet) qui se comprote exactement comme mysql_fetch_array($requet,MYSQL_ASSOC))

ViPHP
AB
ViPHP | 5818 Messages

30 mars 2007, 16:05

Bonjour,

code à corriger en lieu et place de ta ligne existante :

 

    $verdict = mysql_query($test);