Page 1 sur 2

Problème de cache sur une requête...(erreur bizarre)

Posté : 14 mai 2007, 17:47
par momox
Bonjour a tous :)
Je subis quelques déboires depuis que je suis passé a la nouvelle version de wampserver au niveau de mysql.
Une de mes requêtes renvoie toujours une valeur différente de celle dans la base de données... :-k
C'est justement la mon problème, car cette donnée est mise a jour a chaque fois que l'utilisateur visite un post non-lu et est récuperée a chaque tour...

Code : Tout sélectionner

SELECT read_topics FROM forum_read WHERE read_uid='$uid'
Voici la requête en cause...
Sous phpmyadmin, celle-ci me renvoie la valeur que je souhaitais tandis que dans mon appli, qui utilise l'extension mysqli, ben ca me renvoie pas du tout les bonnes données...
Et bien entendu, malgré un joli destroy de la session, impossible de faire apparaitre une valeur autre que celle renvoyée, a savoir a:1:{s:1:"t";a:1:{i:15;i:1179093225;}} qui est un tableau sérialisé, et qui n'est pourtant plus dans la base de données...
Je précise que mon appli n'utilise pas de cache :)

Merci d'avance ;)

Re: Problème de cache sur une requête...(erreur bizarre)

Posté : 14 mai 2007, 18:10
par Hubert Roksor
Err, pour info j'ai rien compris. En revanche, rassure-toi le problème ne vient pas de MySQLi ou du cache de requête de MySQL.
Une de mes requêtes renvoie toujours une valeur différente de celle dans la base de données...
Donc elle renvoit une valeur qui n'est pas dans la base ? ce n'est pas vraiment possible, il doit s'agir d'un bug dans ton code.
malgré un joli destroy de la session
Là non plus j'ai pas compris le rapport entre les sessions et MySQL :?:
a savoir [...] un tableau sérialisé [...] qui n'est pourtant plus dans la base de données
Ah ben fallait commencer par ça :lol: Ben... c'est un bug dans ton code. Tu utilises une variable de session là où il faudrait pas ou un truc du genre.

Posté : 14 mai 2007, 18:53
par momox
Voila le code en question ;)
	private function get_all_new_topics() {
		global $db;
		$s_get_read = "SELECT topic_fid, topic_id, post_date FROM forum_topics as ft, forum_posts as fp WHERE ft.topic_last_pid=fp.post_id AND post_date>'".$_SESSION['lastvisit']."' AND post_uid != '".$db->escape($_SESSION['user_id'])."' AND topic_moved_to IS NULL ORDER BY post_date DESC";
		if(false == ($q_get_read = $db->query($s_get_read))) {
			throw new Exception('<b>General Error :</b><br />Impossible to fetch new topics');
		}
		$new_topics = array();
		while($new_topics_row = $db->fetch($q_get_read)) {
			$new_topics[$new_topics_row['topic_fid']][$new_topics_row['topic_id']] = $new_topics_row['post_date'];
		}
		$this->_forum['new_topics'] = $new_topics;
		$uid = $db->escape($_SESSION['user_id']);
		$s_read_topics = "SELECT read_topics FROM forum_read WHERE read_uid='$uid'";
		$q_read_topics = $db->query($s_read_topics);
		$f_read_topics = $db->fetch($q_read_topics);
        if(!empty($f_read_topics['read_topics'])) {
        	$this->_forum['read_topics'] = unserialize($f_read_topics['read_topics']);
        }
		else {
			$this->_forum['read_topics'] = array();
		}
		return true;
	}
Concernant la variable de session, j'ai eu des bugs bizarres des fois qui n'ont eu pour seule solution que la destruction de la session courante pour en initialiser une autre ;)
La variable en question qui contient le tableau sérialisé est le suivant:
$f_read_topics['read_topics'];
Elle est extraite de la base de données ;)

Posté : 14 mai 2007, 19:23
par Hubert Roksor
Voila le code en question ;)
Et je fais quoi moi, je débugge ? :lol:

À part la délicieuse ironie d'utiliser une variable globale dans une méthode privée je ne sais pas ce qui ne va pas avec ton code, désolé. Pourrais-tu essayer de formuler une question voir si quelqu'un a la réponse ?

Posté : 14 mai 2007, 19:26
par Hubert Roksor
Il y a vraiment un truc que je dois pas comprendre parce que
a savoir [...] un tableau sérialisé [...] qui n'est pourtant plus dans la base de données
...alors pourquoi tu utilises unserialize() sur les données que tu récupères ? :-k

Mets des var_dump() partout, tu finiras par comprendre ce qui se passe, c'est le mieux à faire.

Posté : 14 mai 2007, 20:26
par momox
Justement, je le deserialize pour l'utiliser avec une autre fonction de mon forum.
Mais le véritable problème c'est la requête SQL a mon avis...
Le code de posts lus / non-lus est codé depuis trois mois et n'a pas bougé depuis...

Bon, revenons sur cette histoire de variable.
Quand l'utilisateur lit un post, je l'ajoute au tableau qui avait été récuperé puis déserialisé dans la bdd et je réinsere le tableau sérialisé avec la clé ajoutée.
J'ai fait un echo du tableau sous forme sérialisée juste avant insertion dans la bdd et celui-ci correspond a la valeur présente en base de données après insertion.
Mais quand je récupere cette valeur via mon script, bizarrement, je n'ai plus du tout les bons résultats...
Dans le doute, je fais un echo de la requête, que j'insére dans phpmyadmin et la, suprise, j'ai les bons résultats...
Autre petite chose bizarre, c'est que ce problème est apparu avec la mise a jour de wampserver...
Car hier soir, avant de migrer, tout fonctionnait nickel...

Posté : 14 mai 2007, 20:28
par momox
Il y a vraiment un truc que je dois pas comprendre parce que
a savoir [...] un tableau sérialisé [...] qui n'est pourtant plus dans la base de données
...alors pourquoi tu utilises unserialize() sur les données que tu récupères ? :-k
Justement, c'est ca qui m'étonne moi aussi...
Ma classe pour la bdd n'utilise aucune variable de session et mon code pour récuperer les nouveaux posts non plus...
La question que je me pose donc, c'est comment je fais pour récuperer des résultats n'existant même plus dans la base de données...

Posté : 14 mai 2007, 20:46
par Hubert Roksor
On va essayer de se focaliser sur ce qui est important. L'élément atomique qui fait tout basculer.
J'ai fait un echo du tableau sous forme sérialisée juste avant insertion dans la bdd et celui-ci correspond a la valeur présente en base de données après insertion.
Mais quand je récupere cette valeur via mon script, bizarrement, je n'ai plus du tout les bons résultats...
Ok, ce que tu décris est impossible donc le bug est ici. Qu'insères-tu dans la base et que renvoit ta requête ?
Dans le doute, je fais un echo de la requête, que j'insére dans phpmyadmin et la, suprise, j'ai les bons résultats...
Tu es en train de dire qu'en exécutant la même requête dans phpMyAdmin tu obtiens un résultat différent ? Là encore c'est impossible donc le bug doit se trouver dans ton objet $db.

Posté : 14 mai 2007, 21:02
par momox
Alors, voici la fonction qui me permet de marquer un topic comme lu :
	private function mark_topic_read($topic_id, $forum_id) {
		global $db;
		$this->_forum['read_topics']['t'][$topic_id] = time();
		$s_mark_topic_read = "INSERT INTO forum_read(read_uid, read_topics) VALUES('".$_SESSION['user_id']."', '".$db->escape(serialize($this->_forum['read_topics']))."') ON DUPLICATE KEY UPDATE read_topics='".$db->escape(serialize($this->_forum['read_topics']))."'";
		if(false == $db->query($s_mark_topic_read)) {
			throw new Exception('<b>General Error :</b><br />Impossible to update readed-posts data');
		}
		}
	}
Celle ci met a jour le tableau $this->_forum['read_topics']['t'] avec une clef correpondant a l'id du topic et le timestamp actuel.
Ensuite, le tableau $this->_forum['read_topics'] est serialisé et inseré en base de données.
Ce tableau est récuperé et déserialisé avec la fonction que j'avais données plus haut a chaque chargement du module forum. ;)

Posté : 14 mai 2007, 23:46
par Hubert Roksor
Plutôt que de poster du code PHP est-ce que tu pourrais stp poster les données en question ? Quelles sont les données que tu insères dans la base et quelles sont les données que renvoit la requête ? Que te dis var_dump() ? mets-en partout jusqu'à ce que tu trouves un truc qui ne va pas. Tout le code que tu pourras poster ne servira à rien tant que tu ne seras pas sûr de ce que représente $db, ce que représente $this->_forum, etc...

Posté : 15 mai 2007, 17:51
par momox
Quand je marque le topic comme lu, je fais la requête suivante:

Code : Tout sélectionner

INSERT INTO forum_read(read_uid, read_topics) VALUES('24', 'a:1:{s:1:\"t\";a:1:{i:17;i:1179243962;}}') ON DUPLICATE KEY UPDATE read_topics='a:1:{s:1:\"t\";a:1:{i:17;i:1179243962;}}'
Puis, quand je récupere les données, j'obtiens pour read_topics les données suivantes avec le var_dyump:

Code : Tout sélectionner

string(38) "a:1:{s:1:"t";a:1:{i:17;i:1179243681;}}"
Et sinon, le var dump de $this->_forum donne:

Code : Tout sélectionner

array(3) { ["new_topics"]=> array(0) { } ["read_topics"]=> array(1) { ["t"]=> array(1) { [17]=> int(1179243962) } } ["auths"]=> array(3) { [1]=> array(10) { ["perm_id"]=> string(1) "2" ["perm_gid"]=> string(1) "1" ["perm_fid"]=> string(1) "1" ["read_forum"]=> string(1) "1" ["post_replies"]=> string(1) "1" ["post_topics"]=> string(1) "1" ["post_poll"]=> string(1) "1" ["moderate"]=> string(1) "0" ["edit_post"]=> string(1) "0" ["post_sticky"]=> string(1) "0" } [5]=> array(10) { ["perm_id"]=> string(2) "38" ["perm_gid"]=> string(1) "1" ["perm_fid"]=> string(1) "5" ["read_forum"]=> string(1) "1" ["post_replies"]=> string(1) "1" ["post_topics"]=> string(1) "1" ["post_poll"]=> string(1) "1" ["moderate"]=> string(1) "1" ["edit_post"]=> string(1) "1" ["post_sticky"]=> string(1) "1" } [6]=> array(10) { ["perm_id"]=> string(2) "41" ["perm_gid"]=> string(1) "1" ["perm_fid"]=> string(1) "6" ["read_forum"]=> string(1) "1" ["post_replies"]=> string(1) "1" ["post_topics"]=> string(1) "1" ["post_poll"]=> string(1) "1" ["moderate"]=> string(1) "1" ["edit_post"]=> string(1) "1" ["post_sticky"]=> string(1) "1" } } }
Et pour $db:

Code : Tout sélectionner

object(db_layer)#1 (3) { ["connexion:private"]=> object(mysqli)#2 (0) { } ["nbquery"]=> int(17) ["data:private"]=> bool(true) }
Voila :)
Petite chose, ce matin, j'ai constaté que je récuperais les données inserées hier soir... je suppose que demain j'aurais les données de ce jour...

Posté : 15 mai 2007, 18:29
par Hubert Roksor
Ok, donc en gros tu insères a:1:{s:1:"t";a:1:{i:17;i:1179243962;}} dans la base, quand tu le récupères ça devient a:1:{s:1:"t";a:1:{i:17;i:1179243681;}} et une fois désérialisé ça redevient 1179243962. Ben écoute, il n'y a pas de solution à ce problème. Ton ordinateur est cassé, ou possédé. Essaie un exorciste :-k

PS: je déplace en PHP parce que ce n'est pas un problème SQL

Posté : 15 mai 2007, 19:21
par sadeq
bon, on va s'y remettre.
Ma question est : Peux-tu m'expliquer la forme $db->escape($_SESSION['user_id']) dans ton code suivant:
$s_get_read = "SELECT topic_fid, topic_id, post_date FROM forum_topics as ft, forum_posts as fp WHERE ft.topic_last_pid=fp.post_id AND post_date>'".$_SESSION['lastvisit']."' 
AND post_uid != '".$db->escape($_SESSION['user_id'])."' AND topic_moved_to IS NULL ORDER BY post_date DESC"; 

:!: :?:

Posté : 15 mai 2007, 19:33
par momox
Ok, donc en gros tu insères a:1:{s:1:"t";a:1:{i:17;i:1179243962;}} dans la base, quand tu le récupères ça devient a:1:{s:1:"t";a:1:{i:17;i:1179243681;}} et une fois désérialisé ça redevient 1179243962. Ben écoute, il n'y a pas de solution à ce problème. Ton ordinateur est cassé, ou possédé. Essaie un exorciste :-k

PS: je déplace en PHP parce que ce n'est pas un problème SQL
Non justement, ca ne redevient pas a:1:{s:1:"t";a:1:{i:17;i:1179243962;}}.
a:1:{s:1:"t";a:1:{i:17;i:1179243962;}} est la valeur qui a été inserée
Et la valeur que je récupére a mon plus grand dam est a:1:{s:1:"t";a:1:{i:17;i:1179243681;}}...
Pour sadeq, $db->escape() est un alias de mysqli_real_escape_string(), auquel je compte combler quelques lacunes dues a % dans les requetes de type LIKE.

Posté : 15 mai 2007, 22:44
par momox
Bon, j'ai réinstallé wamp et j'ai fini par identifier le problème, donc finalement, le post avait bel et bien sa place dans le forum Sql et bases de données :P
Donc la requête foireuse est celle-ci:

Code : Tout sélectionner

$s_mark_topic_read = "INSERT INTO forum_read(read_uid, read_topics) VALUES('".$_SESSION['user_id']."', '".$db->escape(serialize($this->_forum['read_topics']))."') ON DUPLICATE KEY UPDATE read_topics='".$db->escape(serialize($this->_forum['read_topics']))."'";
C'est la clause ON DUPLICATE KEY UPDATE qui ne fonctionne pas car j'ai testé l'insert et celui-ci fonctionne.
Donc, la structure de la table est la suivante:
Image
La clé unique est sur read_uid qui correspond a l'id de l'utilisateur.
Donc en principe, si cette clef est deja présente dans la table, on met a jour read_topics, mais ce n'est pas le cas.
Et avant la réinstallation, que je me souvienne, ca fonctionne...

Donc soit Alzeihmer me guette (à 17 ans pourtant... #-o ) soit mon pc me fait des farces...