PHP - Doublons après requête

Fermé
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009 - 30 janv. 2009 à 14:10
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009 - 13 févr. 2009 à 17:36
Bonjour tout l'monde,

merci de m'accueillir sur votre forum où je viens en quête d'aide. :)

Voilà mon problème: j'ai un code qui me sert à créer un nuage de tags en allant chercher dans une table les données, les tags sont fournis par les utilisateurs et il est donc tout à fait possible que ceux-ci choisissent des tags identiques, ce qui fait que je me retrouve avec des doublons, ce que je voudrais éviter!

Le code:

<?php
                   function tags() {
                   function NoAccent ( $chaine ) {

$accents = "ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ";
$noaccents = "AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn";
$chaine = strtr($chaine, $accents, $noaccents);

return $chaine;

}
                   $gt = mysql_query('SELECT tag FROM tags');

while ($arr = mysql_fetch_array($gt)) {
$chaine_tags = $arr['tag'];
                   

$chaine_tags = NoAccent($chaine_tags);

$remplace = array(' de ', ' le ', ' la ', ' pour ', ' un ', ' une ', ' avec ', ' à ', ' et ', ' ou ', ' où ', ' pour ',
 ' mais ', ' donc ', ' or ', ' ni ', 'ne', ' car ', ' les ', ' quand ', ' qui ', ' quoi ', ' en ', ' on ', ' dans ', 
' du ', ' des ');
$par = ' '; 
$chaine_tags = str_replace($remplace, $par, $chaine_tags);

// Supprime les espace en debut et fin de chaine
$chaine_tags = trim($chaine_tags, ' ');

// On decoupe la chaine avec explode, grace au pipe |
$mots = explode(',', $chaine_tags);

// On traite la chaine pr supprimer les doublons
$mots = array_unique($mots);

// On mélange le tableau avec shuffle
shuffle($mots);

// Soit $max est = à l'ensemble du contenu du tableau
// $max = count($mots); // count renvoi le nombre total d'éléments

// Soit on spécifie un nombre max d'éléments à afficher
$max = 25; // par exemple

// pensez bien à choisir l'une ou l'autre variable ci-dessus

// Taille de police en pixel
$font_mini = 10;
$font_maxi = 18;

// Puis on affiche le nuage avec la boucle for
$nuage_tags = '';
for ( $i=0; $i< $max ; $i++ ) : // Début de boucle

// Avec rand, à chaque tour de boucle on choisi
// une taille de police comprise entre $font_mini et $font_maxi
$fontsize = rand($font_mini,$font_maxi).'px';

// plutôt qu'un echo, je préfere créé une variable $nuage_tags, que j'affiche par la suite
// A chaque tour, la variable est complétée avec le .=
$ftag = $mots[$i];
$nuage_tags .='<a style="font-size:'.$fontsize.';" href="tags.php?ltag='.$ftag.'" title="">'.$mots[$i].'</a> ';;

endfor; // Fin de boucle

// Affichage final

echo $nuage_tags; }} 
?>

J'utilise ceci pour enlever les doublons, mais il me semble que finalement ça ne s'applique pas à tout le tableau mais juste à la ligne en cours traitée dans la boucle:
$mots = array_unique($mots);

Là je bloque je ne sais pas trop par quel bout prendre le problème pour le résoudre (sachez que je débute!)...

Votre avis et vos conseils m'intéressent vivement! ;)
A voir également:

8 réponses

Mikey_UFC Messages postés 312 Date d'inscription jeudi 8 mars 2007 Statut Membre Dernière intervention 2 août 2010 1
30 janv. 2009 à 15:41
Jamais utilisé array_merge mais vu que tu récupères ta liste de mots d'après la requête, avec distinct tu es sûr de ne plus avoir de doublons.
1
Mikey_UFC Messages postés 312 Date d'inscription jeudi 8 mars 2007 Statut Membre Dernière intervention 2 août 2010 1
30 janv. 2009 à 15:01
Salut,

Je ne suis pas sûr d'avoir tout compris mais si tu met deistinct dans ta requête, ça ne résoud pas ton problème ?
$gt = mysql_query('SELECT DISTINCT(tag) FROM tags');
0
vlmath Messages postés 794 Date d'inscription vendredi 20 octobre 2006 Statut Contributeur Dernière intervention 4 septembre 2011 160
30 janv. 2009 à 15:04
Salut,

Bienvenue sur CCM !!

Tu ne pourrais pas faire le tri directement dans la requête SQL via un DISTINCT comme ici ?

A bientôt.
0
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009
30 janv. 2009 à 15:27
Hello, merci poir vos réponses! c'est sympa ;)

le distinct j'y avais pensé mais la problématique c'est de sortir le array_unique de la boucle afin qu'il s'applique à tout le tableau et non à la ligne en cours, donc est-ce que spécifié distinct dans la requête pourrait éluder le problème?
faudrait que je teste...

sinon on ma suggèrer cette solution, et après test ça semble fonctionner correctement...:
<?php
                   function tags() {
                   function NoAccent ( $chaine ) {

$accents = "ÀÁÂÃÄÅàáâãäåÒÓÔÕÖØòóôõöøÈÉÊËèéêëÇçÌÍÎÏìíîïÙÚÛÜùúûüÿÑñ";
$noaccents = "AAAAAAaaaaaaOOOOOOooooooEEEEeeeeCcIIIIiiiiUUUUuuuuyNn";
$chaine = strtr($chaine, $accents, $noaccents);

return $chaine;

}

$mots = array();

$gt = mysql_query('SELECT tag FROM tags');

while ($arr = mysql_fetch_array($gt)) {
    $chaine_tags = $arr['tag'];


    $chaine_tags = NoAccent($chaine_tags);

    $remplace = array(' de ', ' le ', ' la ', ' pour ', ' un ', ' une ', ' avec ', ' à ', ' et ', ' ou ', ' où ', ' pour ',
 ' mais ', ' donc ', ' or ', ' ni ', 'ne', ' car ', ' les ', ' quand ', ' qui ', ' quoi ', ' en ', ' on ', ' dans ', 
' du ', ' des ');
$par = ' '; 
$chaine_tags = str_replace($remplace, $par, $chaine_tags);

// Supprime les espace en debut et fin de chaine
$chaine_tags = trim($chaine_tags, ' ');

// On decoupe la chaine avec explode, grace au pipe  et on rajoute les données dans le tableau global
$mots = array_merge($mots, explode(',', $chaine_tags));

}



// On traite la chaine pr supprimer les doublons
$mots = array_unique($mots);

// On mélange le tableau avec shuffle
shuffle($mots);

// Soit $max est = à l'ensemble du contenu du tableau
// $max = count($mots); // count renvoi le nombre total d'éléments

// Soit on spécifie un nombre max d'éléments à afficher
$max = 25; // par exemple

// pensez bien à choisir l'une ou l'autre variable ci-dessus

// Taille de police en pixel
$font_mini = 10;
$font_maxi = 18;

// Puis on affiche le nuage avec la boucle for
$nuage_tags = '';
for ( $i=0; $i< $max ; $i++ ) : // Début de boucle

// Avec rand, à chaque tour de boucle on choisi
// une taille de police comprise entre $font_mini et $font_maxi
$fontsize = rand($font_mini,$font_maxi).'px';

// plutôt qu'un echo, je préfere créé une variable $nuage_tags, que j'affiche par la suite
// A chaque tour, la variable est complétée avec le .=
$ftag = $mots[$i];
$nuage_tags .='<a style="font-size:'.$fontsize.';" href="tags.php?ltag='.$ftag.'" title="">'.$mots[$i].'</a> ';;

endfor; // Fin de boucle

// Affichage final

echo $nuage_tags; }
?>


Qu'est-ce que vous en pensez?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009
30 janv. 2009 à 16:01
Beh moi j'ai jamais utilisé distinct, mais je prends bonne note de ton conseil, j'ai d'ailleurs commencé à me documenter à ce propos...
0
niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010 19
30 janv. 2009 à 16:51
salut, je te propose d'inverser le fonctionnement de ton truc.

il faut que tu fasses les remplacements au moment ou l'utilisateur crée son message et ses tags.

puis, dans ce qu'il a marqué comme tags, : les chiens et les chats
apres transformation: chiens chats

tu utilises la fonction explode() pour isoler chanque mot.

ensuite pour chaque mot, ton programme regarde dans la base s'il y est déja, dans ce cas il associe le post à ce mot via une table contenant un champ qui référence le numéro du post et un champ qui référence le numéro du mot tag. (ces deux champs formant la clé primaire)

si le mot n'y est pas déja, il l'ajoute et l'associe à l'article de la même manière.

de plus, à chaque fois que cela arrive, il suffit d'ajouter +1 dans la table des mots de tag à chaque mot concerné pour indiquer qu'un post de plus l'utilise comme tag. il te faudra par avance génerer les nombres de départ en fonciton des post qui utilisent déja ces tags. (une requete toute bête)

ainsi ce sera propre et sans bavure, par contre à optimiser car ça fait beaucoup de requêtes qu vont d'enchainer dans tes foreach()


l'avantage, c'est que ça fait bosser le serveur mysql quand on enregistre un post, ce qui n'arrive pas toutes les 30 secondes quand même, mais du coup php ne refabrique pas le nuage de tags avec les array et tout le bazar à chaque fois qu'on (re)charge une page ou le nuage de tag est présent
0
Mikey_UFC Messages postés 312 Date d'inscription jeudi 8 mars 2007 Statut Membre Dernière intervention 2 août 2010 1
30 janv. 2009 à 16:55
Ah oui, je ne l'avais pas dit mais je trouvais ça bizarre d'avoir plusieurs fois le même tag dans la base.
0
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009
30 janv. 2009 à 17:07
Ha oui effectivement, j'avais pas vu les choses comme ça... tu penses que c'est trop lourd ma manière de faire?
0
niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010 19 > stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009
4 févr. 2009 à 01:07
ben faire le travail du tableau, de recréer le tag à partir des messages laissés par les utilisateurs, oui c'est long.

mettons que tu aies 100 post, dans chacun les mot clés c'est genre "j'aime les chats"

avec ton explode t'aura déja 3 variables par tag enregistré.. ça va en faire 300 qui vont se succéder. alors ok avec les ordis de maintenant ça ira.

de plus, je remarque que ta boucle while est faite pour ne faire qu'un seul passage, puisque la varaible $mot est utilisée ensuite hors de la boucle. c'est à dire à chaque passage d'un enregistrement, cette varaible est écrasée par une nouvelle variable $mots..

ça qui suppose, pour que ça marche ton nuage, que tous les tags soient enregistrés dans le même enregistrement, or j'espère bien que ce n'est pas le cas..

j'avoue que ton code n'est pas très clair. de plus tu fais varier la taille de police dans ton nuage de façon aléatoire, or elle devrai varier en fonction du nombre de fois ou un message est associé au mot-clé concerné..


voilà solon moi ce que tu dois faire, commeje l'ai dit au dessus:

tu as 3 tables:

les messages (id_message, contenu, etc)
les mot de tag (id_mot, mot, importance)
association mot/message (id_message, id_mot)

1. quand un utilisateur laisse un message, il laisse aussi des mots clés, séparés par une virgule et un espace.
2. là tu utilises ton programme pour explode cette phrase quand tu enregistres le message.
2.1 tu enregistres le message, puis tu récupères le dernier identifiant généré par mysql (normalement la clé primaire de tes messages, dans mon exemple id_message, par: $message_id = mysql_insert_id($ta_connexion);
2.2 tu explode donc les tags qu'il à laissé dans un tableau $mots.
2.3 avec un foreach() , pour chaque mot du tableau, tu vas dans ta table mot pour voir s'il existe déja, si oui, tu en récupères le numéro (donc la ça fait une requete à chaque passage du foreach, mais bon tant pis) id_mot, que tu stockes dans une variable $idmot. s'il n'existe pas, tu le fais entrer dans la base des mots, puis tu en récupères le numéro avec mysql_insert_id() dans $id mot
2.4 (voir plsu loin)
2.5, ensuite, dans ta table association, tu fais entrer les valeurs de $message_id et $idmot dans les champs id_message, id_mot, afin de se rappeler que le message que l'on traite est associé à ce mot clé.
2.6 fin du foreach, on recommence avec le second mot par un passage dans le foreach => 2.3 donc..


ici c'est un choix à faire, concernant la partie 2.4: soit au passage 2.4 tu ajoute dans le champ 'importance' de ma table mot_de_tag +1 pour indiquer que ce mot a un nouvel article qui le référence (quand tu en crées un nouveau ou quand tu en détecte un déja existant), mais si cet article est supprimé e mot ne perdra pas son importance (cependant tu pourra, lors de la suppression d'un artcile enlever 1 à la valeur des mots qui y font référence, avec un ejointure toute simple, cette solution est pas mal), soit apres le foraeach en 3. tu recalcule l'importance de tous les mots en fonction du nombre de fois ou leur numéro est répété dans la table association, c'est à dire +1 à chaque fois qu'un article y est associé. là il faut 2 requetes toutes bêtes: (et que quand tu crées un nouveau mot, ma valeur d'importance se mette toute seule, par un not null et une valeur par défaut: 1

la premiere: $requete = select id_mot, count(id_mot) as nb_fois from association order by id_mot (à vérifier je sais plsu si c'est possible avec mysql), ça te renvoie le nombre de fois ou chaque id_mot est présent.
$execution de la requete = mysql_query etc..
ensuite dans un while $ligne= mysql fetch machin ($execution), tu fais update mot_tag set importance = $ligne[bn_fois] where id_mot = $ligne[id_mot]



voilà, faire ça à chaque enregistrement d'article n'est pas très grave, mais je préfèrerais la premiere solution.


ensuite pour l'affichage de ton nuage, t'as plsu qu'a faire select mot, importance from mot_tag;

et à chaque echo (ou print) tu crées une taille de police en fonction du champ importance, avec un coefficient,

genre taille de police = 1,Xem, x étant int(1/importance*10) (je dis ça au pif hein), la couleur aussi, avec des valeurs rvb calculées à partir de importance, tu peux téclater à faire un arcenciel de taré..

l'étape suivante serait de créer un système de cache pour ce nuage de tags, de sorte qu'il soit lui aussi crée quand on ajoute un article ou en supprime un, puis enregistré dans un fichier et lu à partir de ce fichier au lieu d'attaquer la base de données à chaque fois. je suis en train d'apprendre ça mais ça a pas l'air dur du tout.



voilà je pense que je suis pas très clair, si tu piges pas désolé, au pire fais lire ça à quelqu'un qui s'y connait un peu plus il pigera facilement, car ce sont des trucs basiques que je dis et je les aurais tapés en code plsu rapidement que ce que j'ai mis à les explqiuer. Pasque j'ay connais pas trop trop non plus, mais je sais une chose, avant de commencer à coder, il faut d'abord bien savoir ce que l'on veut faire, et quelles sont les meilleures étapes pour le faire, et ce sans penser à dans quel langage tu code ni rien, mais jsute en logique. Stocker plusieurs mots dans un même enregistrement de table est une erreur selon moi, tout comme faire le traitement explode, calcul de l'importance, etc, à chaque affichage de la page.

Maintenant si j'ai dis d'écormes conneries, faites le moi savoir ceux qui auront eu le courage de venir à bout de ce pavé.

@+
0
niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010 19 > niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010
4 févr. 2009 à 01:20
j'ajoute que pour que mysql_insert_id fonctionne, il fau que les clés primaires de tes messages et de tes mot clés soient en 'auto_increment' mais je suppose que c'est le cas.


dans la table association, tu as donc a chaque ligne un message associé à un mot. ce qui fait que dans ton nuage, tu peux faire un lien en cliquant sur le mot qui va amener à une apge listant tous les messages qui ont été associées à ce mot

la table ça donne ça hein:

id_message // id_mot

1 // 1
1 // 2
1 // 6
2 // 1
2 // 4
2 // 6
3 // 1
3 // 3
etc..

la requete serait

$requete = "SELECT nom_message, messages.id_message, FROM messages, association
WHERE association.id_mot = '".$id_du_mot_cle_demandé."' and
association.id_message = message.id_message";

et ensuite dans une boucle tu fais ta liste avec
echo "<a href=\"message.php?id_message=".$ligne["id_message"]."\">".$ligne["nom_message"]."</a><br />";

ce qui enverrait vers ta page (que j'ai appelé message.php?id_message=numéro_de_message ) qui récupère dans la varaible $_GET["id_message"] le numéro du message à afficher, tu dois déja avoir une page comme ça.
0
niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010 19
4 févr. 2009 à 01:21
xc
0
niahoo Messages postés 247 Date d'inscription lundi 24 décembre 2007 Statut Membre Dernière intervention 23 mai 2010 19
4 févr. 2009 à 01:21
oops je gelere avec le forum mmoi, comment on fait pour supprimer un de ses post ?
0
stefhan Messages postés 5 Date d'inscription vendredi 30 janvier 2009 Statut Membre Dernière intervention 13 février 2009
13 févr. 2009 à 17:36
yes niahoo,

raisonnement très intéressant!

merci d'avoir pris le temps de l'exposer et le développer, c'est très appréciable!!
0