8795 sujets

Développement web côté serveur, CMS

Bonjour à tous et à toutes,

Depuis hier, j'essaie de faire fonctionner correctement un script qui empêcherait les messages doubles (doublons) dans un minichat.

Le code du minichat est basé sur ce tutoriel.

J'ai effectué quelques petites modifications dessus, ce qui donne ce code :


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
    <head>
        <title>Mini-chat</title>
        <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
		<link rel="stylesheet" media="screen" type="text/css" title="mini_chat" href="mini_chat.css" />
    </head>

    <body>
	
<?php

/* Script minichat.

Ce script provient du Site du Zéro et a été modifié par jQz.

Dernière date de modification : 12 juillet 2009.
*/

if(isset($_POST['pseudo']) AND isset($_POST['message'])) // Si les variables existent.
{
    if ($_POST['pseudo'] != NULL AND $_POST['message'] != NULL) // Si on a quelques chose à enregistrer.
	{
	    // D'abord on se connecte à MySQL.
		mysql_connect("localhost", "root", "");
		mysql_select_db("test"); // On séléctionne la base de donnée sur laquelle on veut travailler.
		
		// On utilise les fonctions suivantes pour la sécurité.
		$message = mysql_real_escape_string(htmlspecialchars($_POST['message']));
        $pseudo = mysql_real_escape_string(htmlspecialchars($_POST['pseudo']));
		
                // Requête qui récupère le dernier message posté.
		$verification_doublons = mysql_query("SELECT message FROM minichat ORDER BY ID DESC");
		
		// Début du bloc d'instruction conditionnelle.
		
		if ($_POST['message'] == $message)
		{
			echo 'Vous avez déjà posté ce message.';
		}
		elseif ($_POST['message'] != $message)
		{
			mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '$message', '".time()."')");
		}
						
		// Déconnexion de MySQL.
		mysql_close();
	}
}

// Que l'on ait enregistré des données ou pas...
// On affiche le formulaire puis les 10 derniers messages.
 
// Tout d'abord le formulaire :
?>

<div id="page">
                       
<form action="minichat.php" method="post">
 
<p>	
<label for="pseudo">Pseudo : </label><br />
<input type="text" name="pseudo" maxlength="15" size="20" value="<?php echo $_POST['pseudo']; ?>"

<?php
if (isset($_POST['pseudo']))
    {
	    echo 'value="' . htmlspecialchars($_POST['pseudo']) . '"'; // On utilise la variable super globale $_POST afin de conserver en mémoire le pseudonyme de l'internaute qui aurait déjà remplit le champ pseudo.
	}
?>

 /><br />

<label for="message">Message : </label><br />
<input type="text" name="message" maxlength="255" size="20" /><br />
 
<input type="submit" value="Envoyer" />
</p>
 
</form>

<?php
$pseudo = $_POST['pseudo']; // On récupère la variable pseudo.
$message = $_POST['message']; // On récupère aussi la variable message.

if(!isset($pseudo) AND !isset($message))
    {
// !isset signifie que la variable n'existe pas du tout, donc ça c'est quand il arrive la première fois sur la page.

	    echo "Veuillez saisir votre pseudo et un message.";
    }

elseif(empty($pseudo) AND empty($message) || empty($pseudo) or empty($message)) // Sinon si l'internaute n'as pas remplis le champ pseudo et message OU le champ pseudo ou message, on affiche le texte.
    {
	    echo "<span style='color: #FF0000'><b>Vous devez saisir un pseudo et remplir la zone de saisie !</b></span>";
    }

else // Sinon.
    {
	    echo "Veuillez saisir votre pseudo et un message.";
    }
?>
</div>

<div id="message">
<?php
// On récupère les 10 dernières entrées de la table
// On se connecte d'abord à MySQL

        mysql_connect("localhost", "root", "");
		mysql_select_db("test");
		
		// On utilise la requête suivante pour récupérer les 10 derniers messages :
		$reponse = mysql_query("SELECT * FROM minichat ORDER BY ID LIMIT 0,10");

		
		// Déconnexion de MySQL
		mysql_close();
				
		// On fait une boucle pour afficher les résultats
		?>
        <?php
        while ($donnees = mysql_fetch_array($reponse))
            {
                $timestamp=$donnees['date']; // pour récupérer le timestamp du message
                echo 'message posté le ' . date('d/m/Y \à H\h i\m\i\n \e\t s\s', $timestamp);?>

                    <p>par : <i><?php echo $donnees['pseudo']; ?></i><br /><strong>Message : </strong><?php echo $donnees['message']; ?></p>
<?php
}
		// Fin de la boucle, le script est terminé !
?>
 </div>
    </body>
</html>



Malheureusement, c'est ce bout de code qui paraît coincer :


// Requête qui récupère le dernier message posté.
		$verification_doublons = mysql_query("SELECT message FROM minichat ORDER BY ID DESC");
		
		// Début du bloc d'instruction conditionnelle.
		
		if ($_POST['message'] == $message)
		{
			echo 'Vous avez déjà posté ce message.';
		}
		elseif ($_POST['message'] != $message)
		{
			mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '$message', '".time()."')");
		}


Explication de ce que je cherche à faire :

C'est simple que tout, je cherche à empêcher les doublons.
J'ai connaissance de ce tutoriel mais je ne veux pas l'utiliser, car il faut savoir manier les session et d'autres choses que je n'ai pas encore appris.

Je préfère donc me tourner vers une solution efficace mais plus simple :

Le problème, c'est que actuellement, mon script anti-doublons bloque tout, il m'est impossible de poster un quelconque message.

je vous expose mon raisonnement, que j'ai bâtie avant de commencer à coder :

Minichat, empêcher les doublons :

1. On fait une requête SQL qui va se charger de récupérer le dernier message posté.

2. On utilise les instructions conditionnelles afin de poser des conditions :
2.a Si le message est identique en tout point par rapport au dernier message posté alors on bloque l'envoie et on affiche un message d'alerte.
2.b Sinon si le message est différent par rapport au dernier alors on envoie le message.


Pour ceux qui voudrais tester ce script en local:

Créez une nouvelle base de donnée que vous nommerez 'test'.
Dans cette même BDD, créez une table nommée 'minichat' qui doit contenir quatre champs.

Un premier champ nommé ID de type INT(11) en auto_increment, action primaire.
Un second champ nommé pseudo de type VARCHAR(15) Interclassement latin1_swedish_ci.
Un troisième champ nommé message de type VARCHAR(255) Interclassement latin1_swedish_ci.
En enfin, un dernier champ nommé date de type BIGINT(20).

Et voilà Smiley smile .

En espérant que quelqu'un pourra éclaircir ma lanterne, parce que là, je sèche.
Modifié par jQz (13 Jul 2009 - 22:57)
Salut,

a écrit :
$verification_doublons = mysql_query("SELECT message FROM minichat ORDER BY ID DESC"); 
if ($_POST['message'] == $message) 
Ne te manquerait-il pas, entre ces deux lignes, un truc de ce style :
$row = mysql_fetch_array($verification_doublons);
$message = $row[0];
?
Bonsoir marcv et merci de m'avoir répondu.

Peut-être bien que si mais je n'en suis pas sûr.

J'ai quand même testé ton petit bout de code et voilà le résultat.

Admettons que j'écrive un message de test sans ton code, par exemple je rentre comme pseudo : jQz et comme message Test.

Il m'affiche bien jQz et Test.

J'inclue ton petit bout de code dans le miens, et je réécris un autre message avec le même pseudo mais un contenu différent du précèdent, par exemple :

Hello.

J'envoie ce message et voilà ce qu'il m'affiche :

Pseudo : jQz
Message : Test. au lieu de Hello.
En bref, il reprend le contenu du message précèdent.

Néanmoins, si dans le champ message, j'écris Test., le script anti-doublons fonctionne.

En conclusion, je suis paumé Smiley rolleyes .
Modifié par jQz (13 Jul 2009 - 19:24)
Il faut que tu modifies cette ligne pour que le nouveau message soit inséré.

mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '$_POST[|\'message\']', '".time()."')");

Modifié par kurt11 (13 Jul 2009 - 20:19)
Bonsoir kurt11,

quand j'ai inséré ta ligne de code modifiée, j'ai obtenu l'erreur suivante :

Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in C:\wamp\www\minichat\minichat.php on line 45.
Au temps pour moi, on a pas besoin des " \' ".
mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '$_POST[ message ]', '".time()."')");

Modifié par kurt11 (13 Jul 2009 - 21:43)
Toujours la même erreur.

Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE, expecting T_STRING or T_VARIABLE or T_NUM_STRING in C:\wamp\www\minichat\minichat.php on line 45

Je pense que ce sont les [ ] qui posent problème.
Arf Smiley ohwell j'avais testé avec ce code
echo "'$_GET[id]'";
et ça fonctionnait bien sur mon serveur. Dans c'est cas là, essaie ceci.
mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '".$_POST["message"]."', '".time()."')");
ou ceci Smiley smile :
mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '{$_POST['message']}', '".time()."')");
jQz, avec la correction de kurt plus la mienne, ça devrait fonctionner. Je comprends que tu es en train d'apprendre, donc il est peut-être inutile d'optimiser ; mais à tout hasard, tu pourrais toujours améliorer ton code ainsi :
- tester aussi le pseudo, car si deux personnes différentes disent "Salut", ça bloquera le deuxième
- la variable $message est inutile, $row[0] suffit
- ton elseif ($_POST['message'] != $message) est inutile, un simple else suffit
Modifié par marcv (13 Jul 2009 - 21:44)
Merci à vous deux.

Voilà le code modifié :


// On utilise une requête qui va séléctionner le dernier message et son pseudonyme.
		
		$verification_doublons = mysql_query("SELECT message, pseudo FROM minichat ORDER BY ID DESC");
		
		$row = mysql_fetch_array($verification_doublons);
		$message = $row[0];
			
		// Début du bloc d'instruction conditionnelle.
		
		if ($_POST['message'] == $message AND $_POST['pseudo'] == $pseudo)
		{
			echo 'Vous avez déjà posté ce message.';
		}
		else
		{
			mysql_query("INSERT INTO minichat VALUES('', '$pseudo', '{$_POST['message']}', '".time()."')");
		}


Ça marche à merveille Smiley cligne .

Néanmoins, es-ce quelqu'un pourrait m'expliquer ces deux lignes que je ne comprends pas bien :


$row = mysql_fetch_array($verification_doublons);
		$message = $row[0];


Comme l'a dit marcv :

Je suis en plein apprentissage du PHP.
De manière légèrement simplifiée :
$verification_doublons = mysql_query("SELECT message, pseudo FROM minichat ORDER BY ID DESC");
mysql_query() te renvoit toujours l'intégralité des résultats demandés, sous la forme d'une variable de type ressource. Dans ton cas, c'est $verification_doublons qui contient, une fois la requête effectuée, toutes les lignes de ta table (et il peut y en avoir beaucoup), et chacune de ces lignes contenant les deux champs demandés.
Note : tu pourrais utiliser LIMIT 1 pour ne récupérer que la première ligne. Les autres sont inutiles.
$row = mysql_fetch_array($verification_doublons); 
Tu ne peux pas utiliser directement une ressource, tu dois extraire les informations qu'elle contient. Avec mysql_fetch_array(), tu extrais une ligne de la ressource dans un tableau (nommé $row, ici). Le prochain appel à mysql_fetch_array() extraiera la seconde ligne, et ainsi de suite.
Note : mysql_fetch_array() n'est qu'un moyen parmi d'autres d'extraire les données d'une ressource (cf doc PHP)
$message = $row[0]; 
$row est un tableau PHP contenant les différents champs (colonnes) de la ligne récupérée. Le champ message étant le premier sur la liste de ton SELECT, on le récupère avec $row[0].
Note : telle qu'utilisée ici, mysql_fetch_array() te permet également de récupérer le champ par son nom, plutôt que par son index, à savoir $message = $row["message"];

Voilà, arrivé à ce niveau, $message contient la valeur du champ message de la première ligne retournée par ta requête.
Clair, net et précis, que demander de plus, merci beaucoup.
Encore merci à vous deux pour votre aide Smiley cligne .