Casse-tête: code qui s'exécute deux fois

Détrôa
Invité n'ayant pas de compte PHPfrance

31 août 2010, 13:55

Bonjour,

Je ne suis pas trop certain de l'appartenance débutant/avancé de ce thread mais vu que personne n'a pu me répondre jusque là, je tente l'avancé. ;)

Bref, j'ai déjà fait des tas de pages PHP et c'est la première fois que je me retrouve face à ça: une page qui s'exécute deux fois sans que je ne le lui demande. La page en question est contenue dans une include sur une page vers laquelle je renvoie des données POST venant d'une autre page.

Code de la page contenant l'include de celle qui me pose problème:
<?php
session_start();
$mysqlcon = mysql_connect("localhost", "root", "");
mysql_select_db("cefalweb");
if($_GET['cat'] == 'let3')
{
	require_once("newsmail.php");
}
?>
Et ensuite code de ma page problématique (j'y ai mis plusieurs echo afin de tester le nombre de chargement dans diverses situations):
<?php
if(!empty($_POST))
{
	mysql_query("INSERT INTO newsindex VALUES('','test','0',SYSDATE())");
	$lastid = mysql_insert_id();
	echo '<a href="test.php?cat=let3&conf='.$lastid.'">Valider</a>';
	echo $_SESSION['count'].' - if';
}
elseif(isset($_GET['conf']))
{
	$_SESSION['count']++;
	echo $_SESSION['count'].' - elseif';
	$idn = mysql_real_escape_string(htmlspecialchars($_GET['conf']));
	$idnvraw = mysql_query("SELECT * FROM newsindex WHERE id = '$idn' AND exp = '0'");
	if(mysql_num_rows($idnvraw) != FALSE)
	{
		mysql_query("UPDATE newsindex SET exp = '1' WHERE id = '$idn'");
		echo 'La newsletter a bien été envoyée et est, à présent, stockée dans les archives.';
	}
	else
	{
		echo $_SESSION['count'].' - elseif';
	}	
}
else
{
	echo $_SESSION['count'].' - else';
}
?>
Quant à la table dans laquelle j'écris/lis, il s'agit bien de la table "newsindex" qui contient les champs "id" (INT / 11 / auto_increment), "lien" (VARCHAR / 36), "exp" (INT / 1) et "date" (DATE).

Les écritures/lectures se passent bien, il n'y a que le fait que le code s'exécute deux fois qui pose problème.

Le fonctionnement logique serait:

1.) $_POST envoyé d'une autre page vers "test.php?cat=let3". Si on vient du formulaire de l'autre page, traitement du if qui affiche un lien "test.php?cat=let3&conf=X" où X est l'id retournée par les actions du if.

2.) En cliquant le lien "test.php?cat=let3&conf=X", on revient donc sur la même page PHP mais qui doit effectuer des actions différentes puisque le $_POST n'est plus d'actualité mais à sa place, le $_GET l'est, donc, je désire effectuer les actions du elseif.

Sauf qu'une fois que je clique sur "test.php?cat=let3&conf=X", le elseif se lance deux fois (deux chargements de la page). Par contre, si j'entre manuellement l'adresse dans la barre d'url et que je donne une autre valeur à conf (correspondant à une autre id mise manuellement sur 0 dans la BDD), tout fonctionne parfaitement.

C'est comme si le fait de modifier le dernier enregistrement faisait tout déconner, je suis complètement largué. Avis aux amateurs de casse-tête. ^^' Et merci d'avance à qui aura une idée.

Eléphant du PHP | 217 Messages

31 août 2010, 14:27

Essayez de placer la fonction debug_print_backtrace() dans le fichier qui vous pose problème, vous verez la pile d'exécution de php.

Détrôa
Invité n'ayant pas de compte PHPfrance

31 août 2010, 15:51

Merci pour la réponse,

Lorsque j'utilise cette fonction, je n'obtiens que la mention de require_once (#0 require_once() called at [C:\wamp\www\site\test.php:7]). Rien d'anormal donc si j'ai bien suivi l'utilité de la fonction.

Eléphant du PHP | 55 Messages

31 août 2010, 17:45

Bonjour,
Sauf qu'une fois que je clique sur "test.php?cat=let3&conf=X", le elseif se lance deux fois (deux chargements de la page).
C'est-à-dire ? L'annonce du stockage de la newsletter apparait deux fois ?

Détrôa
Invité n'ayant pas de compte PHPfrance

31 août 2010, 20:28

Non, en fait, au premier passage, il m'affiche bien la confirmation puisque la condition "if(mysql_num_rows($idnvraw) != FALSE)" est remplie, mais dans la liste d'action à effectuer, il change aussi la valeur de "exp" en 1, du coup, au second tour, la requête MySQL ne sélectionne plus rien et donc la condition "if(mysql_num_rows($idnvraw) != FALSE)" n'est plus remplie et c'est le else correspondant qui est exécuté.

Eléphant du PHP | 55 Messages

31 août 2010, 23:58

Alors première question : pourquoi utiliser un if pour cette mise à jour de la table ?

Deuxième question, as-tu mis le code complet de tes deux pages où seulement la partie que tu penses à l'origine du problème ?

Détrôa
Invité n'ayant pas de compte PHPfrance

01 sept. 2010, 10:07

Le if teste qu'une valeur est bien retournée par la requête MySQL juste au dessus, en clair, cela vérifie que la valeur récupérée par le GET existe bien dans la BDD avant de tenter de la modifier dans le if si celui si a sa condition remplie.

Il s'agit bien de tout le code.

Eléphant du PHP | 55 Messages

01 sept. 2010, 17:10

C'est bien ce qu'il me semblait pour l'utilisation du if et je pense qu'il vaut mieux utiliser directement le UPDATE avec une clause WHERE adéquate puis de tester le nombre de lignes affectées pour afficher le message (cela évite une requête inutile) :
$result = mysql_query("UPDATE newsindex SET exp=1 WHERE id=$idn AND exp=0");
if(mysql_num_rows($result)) {
  echo 'La newsletter a bien été envoyée et est, à présent, stockée dans les archives.';
}
else {
  echo 'Cette newsletter n\'existe pas ou a déjà été envoyée.';
}
Pour finir sur le SQL, je te conseille aussi fortement de modifier le nom de ton champ date car il s'agit d'un mot réservé en SQL et cela peut t'occasionner des comportements imprévus.

Pour ton soucis proprement dit, il n'y a aucune raison pour que ce code s'effectue deux fois en l'état et le problème vient forcément d'ailleurs. En tout cas, chez moi, la page ne se charge qu'une seule fois.

Détrôa
Invité n'ayant pas de compte PHPfrance

02 sept. 2010, 11:40

Merci beaucoup pour ces conseils, j'en tiendrai compte, et maintenant que je sais cela à propos de "date", je vais me renseigner sur d'autres termes "réservés" car je me rends compte que j'emploie souvent des noms de champs génériques comme id, index, etc. et du coup, je me dis que d'autres de ces termes sont peut-être du même acabit.

Concernant le problème, je l'ai résolu et il ne venait pas réellement de PHP mais plutôt du navigateur: puisque la page était toujours en cours de développement, je ne me suis pas soucié d'inclure un en-tête HTML correct spécifiant le charset... Grave erreur vu que Firefox n'est pas le plus apte à détecter cela correctement, du coup, la moindre présence d'un caractère un peu fantaisiste tel un accent faisait relancer la page par le navigateur, le serveur était donc bien obligé d'exécuter le code une seconde fois...

Eléphant du PHP | 55 Messages

02 sept. 2010, 20:47

Voici la liste

ViPHP
ViPHP | 5462 Messages

02 sept. 2010, 21:02

ici aussi pour mysql

Détrôa
Invité n'ayant pas de compte PHPfrance

03 sept. 2010, 09:14

Merci beaucoup!