J'essaie de faire en sorte qu'un utilisateur inscris sur mon site puisse ajouter des articles en favoris. Et ensuite lorsqu'il se rend sur la page "Mes Favoris", cela affiche les articles en favoris. J'ai donc créée une table favoris qui contient un ID (ID du favoris), IDarticle et pseudo.
Lorsque le membre clique sur "Ajouter en favoris" :
Input type POST avec input type hidden contenant l'IDarticle. En cliquant sur Ajouter en favoris , il se passe :
Ensuite pour afficher les articles en favoris (Je débute en jointures donc je ne sais pas si c'est correct : )
prepare(SELECT * FROM articles INNER JOIN favoris ON articles.ID = favoris.IDarticle WHERE favoris.pseudo = :pseudo) execute (array('pseudo' => $SESSION['pseudo']))
Bien entendu, ne vous inquiétez pas pour la syntaxe, j'ai juste écris cela au brouillon pour savoir si c'est comme ça que cela doit être fait tant au niveau de la rapidité de la requête, au niveau de l'INNER JOIN ou encore pour savoir si il y a plus rapide..
<?php
if (isset($_SESSION['statut']))
{
if (isset($_GET['ID']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT 1 FROM favoris WHERE pseudo = :pseudo AND IDarticle = :IDarticle');
$requete->execute(array('pseudo' => $_SESSION['pseudo'], 'IDarticle' => $_GET['ID']));
if ($requete->fetch())
{
echo "Vous avez déjà ajouté cet article en favoris."; ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=index.php" />
<?php
}
else
{
$insert = $bdd->prepare('INSERT INTO favoris(IDarticle, pseudo) VALUES(:IDarticle, :pseudo)');
$insert->execute(array('IDarticle' => $_GET['ID'], 'pseudo' => $_SESSION['pseudo']));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !"; ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=index.php" />
<?php
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
echo "Vous devez vous connecter";
}
FAVORIS.PHP
<?php
if (isset($_SESSION['statut']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT article.ID, favoris.ID, favoris.IDarticle, favoris.pseudo FROM articles INNER JOIN favoris ON articles.ID = favoris.IDarticle WHERE favoris.pseudo = :pseudo ORDER BY favoris.ID DESC');
$requete->execute(array('pseudo' => $_SESSION['pseudo']));
while ($donnees = $requete->fetch())
{
///
}
if ($requete->fetchColumn())
{
echo "Vous n'avez aucun article en favoris.";
}
}
else {
echo "Vous devez vous connecter pour voir votre liste des contributions."; ?>
SUPPRIMER-FAVORIS.PHP
<?php
if (isset($_SESSION['statut']))
{
if (isset($_GET['ID']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT pseudo FROM favoris WHERE ID = :ID');
$requete->execute(array('ID' => $_GET['ID']));
$donnees = $requete->fetch();
if ($donnees['pseudo'] != $_SESSION['pseudo'])
{
echo "Une erreur s'est produite !";
}
else
{
$requete = $bdd->prepare('DELETE FROM favoris WHERE ID = :ID AND pseudo = :pseudo');
$requete->execute(array('ID' => $_GET['ID'], 'pseudo' => $_SESSION['pseudo']));
echo "L'article a bien été supprimée de vos favoris !";?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
}
else
{
echo "Une erreur s'est produite !";?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./index" /><?php
}
}
else
{
echo "Vous devez vous connecter";
}
Mes problèmes :
1) Avec 500 membres qui ajoutent en moyenne 10 citations, cela ferait des milliers de ligne seulement dans la table favoris, cela ne va pas supporter non ?
2) Dans FAVORIS.PHP, la condition pour vérifier si le membre qui regarde ses favoris n'en a ajouté aucune ne marche pas et je ne vois pas vraiment pourquoi..
3) Mes requêtes sont elles optimisées et mes conditions sont-elles bonnes ? (c.a.d, c'est ce qu'il faut ou on peut faire encore plus court ? )
Voila !
Merci à vous pour votre aide. Cordialement.
EDIT : Désolé pour le double post mais cela aurait été illisible et trop long si j'avais édité le premier post. Merci pour votre compréhension.
Concernant l'ID du membre, il faudrait faire une jointure avec 3 tables si je veux mettre l'ID (car après il faut récupérer l'ID qui correspond au pseudo en session et cela se trouve dans la table users.) Ainsi, en mettant le pseudo du membre dans la table favoris, j'ai simplement à faire WHERE pseudo = session pseudo autant dans l'INSERT que dans le SELECT... Sinon, en effet, j'ai pensé à mettre l'ID mais dans l'ajout de favoris par exemple, il faudrait rajouter une requête seulement pour récupérer l'ID de l'user... et cela alourdirait le script non ?
Par contre concernant l'explode c'est une excellente idée ! Pour 500 membres, cela fera que 500 lignes mais après il faut faire une condition pour voir si le pseudo existe déjà, si OUI, rajouter l'ID dans ID_article, sinon, créer une nouvelle ligne... Et surtout, si je fais INSERT pour l'ID du nouvel article, cela va supprimer l'ancienne valeur de ID_article non ?
c'est pour cela qu'il est toujours préférable de travailler DES LE DÉPART avec l'ID du membre, au leu du pseudo, un pseudo peut être (ou en tout cas devrais être) modifiable par l'user (et là, plantage de ton script de favoris). De plus, admettons que tu ai un user "Roi_du_web", il à 10 favoris, puis il se désinscrit.
1 ans plus tard, j'arrive et je m'inscrit sous "Roi_du_web", mon inscription à toutes les chance de passer, vu que l'ancien c'est désinscrit, et si tu n'à pas supprimer TOUTES les traces de l'ancien user, hop, je récupère son historique (sur un historique ou des favoris, c'est pas dramatique, je te l'accorde, mais les données privées/confidentiel....aïe !)
ensuite, pour rajouter un ID_d'article, tu tente de récupérer dans ta table la liste des ID_article.
si elle n'existe pas, tu fait un INSERT et si elle existe, tu la récupère, tu la transforme en array(avec explode).
puis tu fait un array_push pour la MAJ de la liste, reste plus qu'à faire un implode pour re-créer un string que tu UPDATE dans ta BDD.
Le principe pourrais être simplifier en rajoutant simplement l'ID du l'article concerné directement à la fin du string, mais la génération de l'array apporte plus de souplesse et permet de vérifier facilement si cet id ne figure pas DÉJÀ dans la liste.
Cette technique permet de pouvoir créer plus facilement des fonctions :
- function list_favoris(ID_membre) pour voir la liste des articles favoris
- function ajout_favoris(ID_membre, ID_article) ajout d'un favoris dans la liste (si cet ID n'y figure pas déjà), ou création de la liste si elle n'existe pas
- function suppr_favoris(ID_membre, ID_article) suppression d'un favoris dans la liste (si la liste existe ET si cet ID y figure)
Dans ce cas, dans mon script de connexion utilisateur, je vais stocker l'ID dans $_SESSION['ID'] comme ça je pourrais le réutiliser après. Ce serait donc quelque chose comme ça ? :
<?php
if (isset($_SESSION['statut']))
{
if (isset($_GET['ID']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT 1 FROM favoris WHERE IDpseudo = :IDpseudo AND IDarticle = :IDarticle');
$requete->execute(array('IDpseudo' => $_SESSION['IDpseudo'], 'IDarticle' => $_GET['ID']));
if ($requete->fetch())
{
echo "Vous avez déjà ajouté cet article en favoris."; ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=index.php" />
<?php
}
else
{
$requete = $bdd->prepare('SELECT IDpseudo, IDarticle FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $_SESSION['IDpseudo']));
if($requete->fetch())
{
$insert = $bdd->prepare('INSERT INTO favoris(IDarticle) VALUES(:IDarticle) WHERE IDpseudo = :IDpseudo');
$insert->execute(array_push('IDarticle' => explode("/", $_GET['ID'])));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
}
}
else
{
$insert = $bdd->prepare('INSERT INTO favoris(IDarticle, pseudo) VALUES(:IDarticle, :pseudo)');
$insert->execute(array('IDarticle' => $_GET['ID'], 'pseudo' => $_SESSION['pseudo']));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
echo "Vous devez vous connecter";
}
Je ne sais pas si j'ai bien fait mais j'ai essayé.
En faite, pour pouvoir ajouter des citations, il faut que l'utilisateur soit connecté et lorsqu'il se connecte, j'initialise $_SESSION['statut'], $_SESSION['pseudo'] et $_SESSION['IDpseudo']. Dans la page principale avec tous les articles, il y a un bouton pour ajouter en favoris. Le bouton est comme ceci : <a href="..../ajout-favoris?ID=<?php echo $ID; ?>">Ajouter en favoris</a> donc je peux récupérer l'ID dans ajout-favoris.
Et le SELECT 1 c'était pour un (mauvais) contrôle de l'existence.. Donc, cela devrait ressembler à cela après modifications :
<?php
if (isset($_SESSION['statut']))
{
if (isset($_GET['ID']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT 1 FROM favoris WHERE IDpseudo = :IDpseudo AND IDarticle = :IDarticle');
$requete->execute(array('IDpseudo' => $_SESSION['IDpseudo'], 'IDarticle' => $_GET['ID']));
if ($requete->rowCount()<1)
{
$insert = $bdd->prepare('INSERT INTO favoris(IDarticle) VALUES(:IDarticle) WHERE IDpseudo = :IDpseudo');
$insert->execute(array('IDarticle' => explode("/", $_GET['ID'])));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
header('Location: index.php');
}
else
{
$insert = $bdd->prepare('UPDATE favoris SET(IDarticle, pseudo) VALUES(:IDarticle, :pseudo)');
$insert->execute(array_push('IDarticle' => $_GET['ID'], 'pseudo' => $_SESSION['pseudo']));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
header('Location: index.php');
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
echo "Vous devez vous connecter";
}
Non ?
Merci encore pour tes conseils et réponses. Cordialement.
Bon, après avoir bien relu tes messages et avoir relu également la doc de chacune des notions j'ai réussi à faire ceci :
<?php
if (isset($_SESSION['statut'])) /// Pour voir si l'user est connecté
{
if (isset($_GET['ID'])) /// Pour voir si il y a bien l'ID de l'article dans l'URL
{
include('connexion.php'); /// connexion à la BDD
$requete = $bdd->prepare('SELECT 1 FROM favoris WHERE IDpseudo = :IDpseudo'); /// requete pour voir si l'user existe déjà dans favoris puisque 1 user = 1 ligne
$requete->execute(array('IDpseudo' => $_SESSION['ID']));
if($requete->rowCount()<1)
{
$requete->closeCursor();
$requete = $bdd->prepare('INSERT INTO favoris(IDarticle, IDpseudo) VALUES(:IDarticle, :IDpseudo)');
$requete->execute(array('IDarticle' => $_GET['ID'], 'IDpseudo' => $_SESSION['ID'])); echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
$requete->closeCursor(); ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
else
{
$requete = $bdd->prepare('SELECT IDarticle, IDpseudo FROM favoris WHERE IDpseudo = :IDpseudo'); $requete->execute(array('IDpseudo' => $_SESSION['ID']));
if ($donnees = $requete->fetch())
{
$IDarticle = $donnees['IDarticle']; $articles = explode("/", $IDarticle); array_push($articles, $_GET['ID']); $articles_implode = implode("/", $articles); $requete->closeCursor();
$requete = $bdd->prepare('UPDATE favoris SET IDarticle = :IDarticle WHERE IDpseudo = :IDpseudo'); $requete->execute(array('IDarticle' => $articles_implode, 'IDpseudo' => $_SESSION['ID'])); echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
$requete->closeCursor(); ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
Vous devez vous connecter...
}
?>
Voilà, donc j'ai testé et cela marche... Si le membre n'existe pas cela rajoute une ligne, si il existe, cela update avec explode, array_push, implode mais je ne sais pas ou placer et comment placer les messages d'erreurs suivants :
- Si l'user a déjà ajouté l'article en favoris - Si l'ID de l'article n'existe pas... (faut t'il créer une 5ème requête pour voir si l'ID de l'article existe dans la table articles ? )
Ensuite, pourrais-tu m'expliquer un peu plus ce que tu entendais par la création des functions pour afficher la liste, ajouter ou supprimer un favoris ?
Merci beaucoup pour ton aide. Et en me donnant aucun code, cela ma permit de bien chercher et de comprendre chaque fonctions. Il manque plus que les erreurs et la création des fonctions et leurs utilisation et c'est bon !
Cordialement.
EDIT : Après un peu de recherche, j'ai rencontré la fonction in_array qui permet de voir si un élément existe dans un tableau... Je ne sait pas si cela est correcte mais j'ai fais ceci (qui fonctionne)
$requete = $bdd->prepare('SELECT IDarticle, IDpseudo FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $_SESSION['ID']));
if ($donnees = $requete->fetch())
{
$IDarticle = $donnees['IDarticle'];
$articles = explode("/", $IDarticle);
if (in_array($_GET['ID'], $articles))
{
echo "Vous avez déjà ajouté cet article en favoris."; ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=index.php" /><?php
}
else
{
array_push($articles, $_GET['ID']);
$articles_implode = implode("/", $articles);
$requete->closeCursor();
$requete = $bdd->prepare('UPDATE favoris SET IDarticle = :IDarticle WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDarticle' => $articles_implode, 'IDpseudo' => $_SESSION['ID']));
echo "L'article ".$_GET['ID']." a été ajoutée en favoris !";
$requete->closeCursor(); ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
}
J'ai a peu pres tout lu et je vois que tu avances bien.
Je n'sais pas si tu l'as deja fait, mais pour verifier que l'id du favoris existe, tu as juste a faire une requete au moment où l'utilisateur arrive sur la page favoris.php?id=X
Tu fais un SELECT COUNT et s'il te renvoi un cest qu'il existe!
Par ailleurs, tu peux, avant meme cette requête, verifier que le $_GET est bien un chiffre (fonction is_numeric de PHP), ca optimisera un peu ton code pour la sécurité
EDIT: Tes requetes sont déjà plus ou moins sécurisées avec PDO
Merci de ta réponse Paupote, donc, après les modifications de vérifications (existence article et format ID), cela donne ça :
<?php
if (isset($_SESSION['statut']))
{
if (isset($_GET['ID']) && is_numeric($_GET['ID']))
{
include('bdd.php');
$requete = $bdd->prepare('SELECT 1 FROM articles WHERE ID = :IDarticle');
$requete->execute(array('IDarticle' => $_GET['ID']));
if($requete->rowCount() == 1)
{
$requete->closeCursor();
$requete = $bdd->prepare('SELECT 1 FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $_SESSION['ID']));
if($requete->rowCount()<1)
{
$requete->closeCursor();
$requete = $bdd->prepare('INSERT INTO favoris(IDarticle, IDpseudo) VALUES(:IDarticle, :IDpseudo)');
$requete->execute(array('IDarticle' => $_GET['ID'], 'IDpseudo' => $_SESSION['ID']));
echo "L'article ".$_GET['ID']." a été ajouté en favoris !";
$requete->closeCursor(); ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
else
{
$requete = $bdd->prepare('SELECT IDarticle, IDpseudo FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $_SESSION['ID']));
if ($donnees = $requete->fetch())
{
$IDarticle = $donnees['IDarticle'];
$articles = explode("/", $IDarticle);
if (in_array($_GET['ID'], $articles))
{
echo "Vous avez déjà ajouté cet article en favoris."; ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=index.php" /><?php
}
else
{
array_push($articles, $_GET['ID']);
$articles_implode = implode("/", $articles);
$requete->closeCursor();
$requete = $bdd->prepare('UPDATE favoris SET IDarticle = :IDarticle WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDarticle' => $articles_implode, 'IDpseudo' => $_SESSION['ID']));
echo "L'article ".$_GET['ID']." a été ajouté en favoris !";
$requete->closeCursor(); ?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
}
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
echo "Une erreur s'est produite !";
}
}
else
{
echo "Vous devez vous connecter.";
}
?>
Donc la, j'ai testé et tout marche. J'aimerais juste savoir si c'est normal d'avoir 5 requêtes dans une page ? Je veux dire c'est pas quelque chose d'incroyable, beaucoup de sites doivent en avoir autant non ?
Et surtout, comment je pourrais ajouter une fonction pour afficher mes favoris par exemple. Enfin je vois ce que je metterais dans la fonction (un SELECT, un implode et une boucle pour afficher toutes les citations) mais comment je fais appel à cette fonction ? Un simple <?php afficher_favoris(); ?> sur la page d'affichage des favoris suffit ?
Donc, j'ai fais la fonction permettant d'afficher les favoris. La voici :
FUNCTIONS-FAVORIS.php
function afficher_favoris($IDpseudo) {
include('connexion.php');
$requete = $bdd->prepare('SELECT IDpseudo, IDarticle FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $IDpseudo));
if ($donnees = $requete->fetch())
{
$requete->closeCursor();
$articles = array_reverse(explode("/", $donnees['IDarticle'])); // reverse pour faire afficher le dernier favoris en premier
foreach($articles as $k => &$v)
{
$ID = $articles[$k];
$requete = $bdd->prepare('SELECT ID, idname, article, auteur, idauteur FROM articles WHERE ID = :IDarticle');
$requete->execute(array('IDarticle' => $ID));
while ($donnees = $requete->fetch())
{ ?>
///Affichage des articles
LIEN POUR SUPPRIMER L'ARTICLE ?
<?php
}
}
}
else
{
echo "Il n'y a aucun favoris !";
}
}
Est-ce que c'est bien un foreach dans un while qu'il fallait faire ? et
Je ne sais pas si j'ai bien fait de mettre tout dans le fichier functions et surtout, maintenant que le lien pour supprimer doit être dans la function pour afficher je ne sais pas comment incorporer ma fonction pour supprimer ? Il faut faire une fonction dans une fonction ?
Merci pour votre aide. Cordialement.
EDIT : Par contre, dans mon cas, j'aimerais connaître l'intéret de faire passer l'ajout, la liste et la suppression de favoris par des fonctions ? Cela me fait créer un fichier en plus (fonctions_favoris) et je pourrais très bien mettre le code de la fonction directement dans ajout favoris...
EDIT 2 : Mon code pour la suppression :
if (isset($_SESSION['grade']))
{
if (isset($_GET['ID']) && is_numeric($_GET['ID']))
{
include('connexion.php');
$requete = $bdd->prepare('SELECT IDpseudo, IDarticle FROM favoris WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDpseudo' => $_SESSION['ID']));
$donnees = $requete->fetch();
$articles = explode("/", $donnees['IDarticle']);
if (in_array($_GET['ID'], $articles))
{
foreach ($articles as $k => &$v)
{
if ($v == $_GET['ID'])
{
unset($articles[$k]);
}
}
$articles = implode("/", $articles);
$requete->closeCursor();
$requete = $bdd->prepare('UPDATE favoris SET IDarticle = :IDarticle WHERE IDpseudo = :IDpseudo');
$requete->execute(array('IDarticle' => $articles, 'IDpseudo' => $_SESSION['ID']));
echo "L'article a bien été supprimée de vos favoris !";?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./favoris" /><?php
}
else
{
echo "Cet article n'est pas dans vos favoris";
}
}
else
{
echo "Une erreur s'est produite !";?><META HTTP-EQUIV="Refresh" CONTENT="1; URL=./index" /><?php
}
}
Donc après tests, tout marche. J'aimerais juste savoir si mes requêtes sont bien optimisées et sécurisées.
L'intérêt de l'affichage des favoris dans une fonction c'est que tu pourras l'utiliser sur une autre page (même si ici tu le fais pas ça peut tjrs s'avérer utile par la suite)
Voilà, si tout fonctionne il n'y à plus de problème.
Le problème avec le foreach c'est qu'à chaque tour il fait une requête. Mais ça je ne vois pas comment tu pourrais y échapper avec la méthode de tout stocker sur un enregistrement..
à la fin de tes requêtes, pour libérer un peu dans chaque requête et contrôle et sécurise la validité de tout ce que tu utilise à l'intérieur d'une requête, ne fait JAMAIS confiance à ce qui provient d'un utilisateur.
@Paupote : Oui, apparement, en sortant la requête du foreach, cela ne marche pas... Mais je ne pense pas qu'il y aurait plusieurs milliers de favoris.. Je pourrais limiter le nombre de favoris par personne, ce serait mieux non ?
@babasdu24 : J'ai justement fais attention à la fermeture de mes requêtes après tes précédents messages. Et normalement, il y a en à la fin de chaque requête la... Et qu'est-ce que je pourrais faire pour sécuriser encore plus ? Les requêtes préparés et is_numeric ne sont pas suffisants ?
Pas bête, tu pourrais limiter par exemple récupérer les 5 ou 10 derniers favoris de ton array, et lancer ta requête avec le while que sur ceux-ci, et, avec peu d'ajax (vraiment minime, donner la possibilité a l'user d'en charger plus s'il en ressent le besoin, en attendant, t'économise ton serveur )
pour la fermeture de requête, j'en vois 2 qui manque (celle du WHILE et celle de ton UPDATE)
foreach($articles as $k => &$v)
{
$ID = $articles[$k];
$requete = $bdd->prepare('SELECT ID, idname, article, auteur, idauteur FROM articles WHERE ID = :IDarticle');
$requete->execute(array('IDarticle' => $ID));
while ($donnees = $requete->fetch())
peut être remplacer par :
foreach($articles as $ID)
{
$requete = $bdd->prepare('SELECT ID, idname, article, auteur, idauteur FROM articles WHERE ID = :IDarticle');
$requete->execute(array('IDarticle' => $ID));
while ($donnees = $requete->fetch())
sauf si tu à besoin de la clef de l'array ailleurs, auquel cas il vaudra mieux écrire :
foreach($articles as $KEY => $ID)
Les nom des variables n'ont pas d'importance, tu peut mettre celles que tu veut, en revanche, c'est vachement plus lisible comme ça !
Il est possible qu'un jour, un user se retrouve avec dans ces favoris un article qui, pour une raison ou une autre, aura été supprimé, cette exception devrais être gérée.
Pour la sécurité, on peut toujours mieux faire (enfin, je pense qu'on en fait jamais assez), mais c'est un autre débat, tu as déjà une protection
Alors pour les closeCursor(), c'est bon. Pour le raccourcis dans le foreach(), c'est bon. Pour charger les articles en AJAX, c'est bon. Seulement, vu que ma requete est dans un foreach, le LIMIT ne fonctionne pas...
Et en effet, il faudrait que je rajoute une requete/condition pour voir si l'article existe mais il faut que je le fasse seulement si l'user à un seul favoris. Parce que j'ai testé et si l'user à deux favoris dont un qui n'existe plus la base, il affiche seulement celui qui existe, sans message d'erreurs.
J'ai reflechi un peu, et ce que tu pourrais faire cest un systeme de compteur a l'arrivé sur la page, je m'explique:
Sur ta page a l'arrivée, tu initialises le nombre "d'affichages" quelque part ( par exemple dans un div avec l'attribut data, que tu pourra recuperer facilement avec du jQuery)
Maintenant ton module PHP qui va afficher les 5 favoris de plus, tu refais ta requete du membre connecté, mais cette fois ci, au lieu de prendre les 5 premiers, tu commencera a en prendre 5 nouveaux a partir de (5 * 1) + 1 (le *1 correspondant au data et le +1 te permet de commencer au 6eme)
N'oublie pas de mettre a jour ton data-affichage en l'incrémentant de 1 pour qu'au prochaine affichage il te prendra les favoris a partir de (5 * 2) + 1, soit le 11e jusqu'au 15e
Voilà, j'espere que tu as compris, ca a l'air compliqué avec tout ce texte, mais une fois que tu as compris, cest tout simple.
D'accord je vois ! Cela semble être l'unique solution. J'ai commencé comme ceci :
$articles = array_reverse(explode("/", $donnees['IDarticle']));
$count = count($articles);
if ($count <= 5)
{
foreach($articles as $ID)
{
$requete = $bdd->prepare('SELECT ID, idname, article, auteur, idauteur FROM articles WHERE ID = :IDarticle');
$requete->execute(array('IDarticle' => $ID));
while ($donnees = $requete->fetch())
{
AFFICHAGE DES ARTICLES
$requete->closeCursor();
}
}
}
else
{
}
Mais je ne sais pas quoi mettre dans le else parce que même si j'arrive a faire une condition sur le nombre d'articles dans l'array, comment en afficher seulement 5 après ?
Merci encore.
Je met le script que j'utilise sur toutes mes pages pour l'affichage 'Afficher plus' :
$(function() {
$('.more').live("click",function()
{
var ID = $(this).attr("id");
if(ID)
{
$("#more"+ID).html('<img src="./images/moreajax.gif" />');
$.ajax({
type: "POST",
url: "./ajax_more",
data: "lastmsg="+ ID,
cache: false,
success: function(html){
$("ul#updates").append(html);
$("#more"+ID).remove();
}
});
}
else
{
$(".morebox").html('<div class="button_more">Tous les articles ont été chargées !</div>');
}
return false;
});
});
Bah ce que tu peux faire dans le else, s'il y a plus de 5 articles pour le membre, par exemple 12.
Etant donné que tu sais a partir de combien afficher (avec la méthode que je t'ai décrite 5* (la variable)), ce que tu peux faire, cest supprimer les X premiers favoris de ta variables $articles.
De ce fait, s'il en a 12 et que tu va afficher les 5 suivants, ET sachant que tu en a deja 5 sur ta page, tu va supprimer les 5 premiers de ta variable $articles.
Du coup, ta $articles comptera 7 favoris :
Si le nb de favoris de $articles et < 5 => tu affiches le reste, sinon, il faut te prendre les 5 premiers sur les 7 (Avec un compteur dans le foreach, tu compte le nombre de tour et au bout du 5eme, tu n'affiche plus les favoris restants (ici 2)
Par ailleurs, dans les data de ton AJAX, il faut passer en parametre le data que je t'avais explique plus haut! Ca te permettra de savoir a partir de combien de favoris tu pourra commencer a afficher les 5 suivants
On a beaucoup parlé d'AJAX sur ce sujet, mais après relecture des premiers messages j'ai peut-être quelques suggestions à faire en ce qui concerne l'optimisation :
Il serait sage d'également conserver l'ID du membre dans une session ; celui-ci pourrait être joint à toutes les actions effectuées sur le site (l'envoi de commentaires par exemple) et on pourrait s'en servir pour les favoris.
La table des favoris est une table de pivot, c'est-à-dire qu'elle fait le lien entre les membres et les contenus que ceux-ci peuvent ajouter en favoris. Souvent, de telles tables peuvent atteindre des tailles impressionnantes et il est bon de se soucier de la performance. Heureusement, une bonne optimisation permettra de tout retrouver facilement. MySQL peut facilement repérer une rangée à l'intérieur d'une table qui contient 1 000 000 000 d'enregistrements en moins de 30 opérations, si tout est bien organisé.
Pour éviter les complications, l'idéal serait de créer une table à deux champs seulement : ID_membre et ID_contenu (ID_article si tes contenus sont des articles).
Ensuite, on va créer un index primaire sur les deux champs, ID_membre en premier et ID_contenu en deuxième. Comme cela, tous les favoris d'un même membre se retrouveront au même endroit. Lors de la recherche, le moteur de la base n'aura qu'à trouver cet endroit et à en sortir les favoris, dans un bloc.
De cette manière, afficher tous les favoris d'un membre sera ultra-rapide, de même que rechercher le favori X d'un membre Y, qu'on effectue de cette manière :
... WHERE ID_membre = :id_membre AND ID_contenu = :id_contenu
On peut utiliser cette syntaxe pour les UPDATE (je doute qu'on ait besoin de cette instruction) ou les DELETE. Il est très important, lors de la clause WHERE, de spécifier l'ID du membre avant l'ID du contenu, de manière à respecter l'ordre de l'index.
Par après, cette table ne devrait éprouver aucun problème de fonctionnement, et ce jusqu'à de très grandes échelles.
@Ciphered : Pour tes trois premiers points, c'est exactement ce que j'ai fais. Par contre, concernant le quatrième, cela n'est plus possible plus que c'est une ligne par membre. C'est à dire que si le membre à mis en favoris les articles 7 ,14 et 20. Le champs ID_article de ce membre sera : 7/14/20
Donc cela n'est plus possible d'exploiter le champs sans faire un explode avant et encore, il faut passer par un foreach...
@Paupote, Ciphered : C'est dommage que tout cela devienne si compliquer seulement parce que je ne peux pas utiliser LIMIT dans ma requête. Quel aurait été l'autre moyen pour laisser mon script ajax comme tel ? foreach est t'il le seul moyen ?
Tu devrais donc restructurer ta base de données tandis que tu peux encore le faire. Utiliser un schéma dans les règles permettra de nombreuses choses. Sans cela, comment peut-on compter le nombre de personnes qui ont ajouté un article X à leur favoris ?
En ce qui concerne le script AJAX, je peux peut-être tenter des suggestions :
On charge les enregistrements par blocs de N favoris
Lorsqu'on entame le chargement des enregistrements suivants, on compte le nombre de favoris qui ont déjà été chargés, et on l'envoie en paramètre pour la clause LIMIT : LIMIT :nbEnrCharges, :nbACharger
Après le chargement, on ajoute le nombre d'enregistrements reçus au compteur et on affiche les nouveaux résultats à la suite des précédents
Mais encore une fois, il faudra adopter le système qui a été recommandé. Il ne faut pas s'en faire pour la performance, tout sera très optimisé et rapide.
Désolé pour ma réponse tardive, j'ai eu un petit problème de connexion internet.
Merci encore pour ta réponse Ciphered mais mon schéma de table favoris n'est t'il pas dans les règles ? C'est exactement ce que tu as proposé. Une table à deux champs IDmembre et IDarticles ...
Non, car dans ton schéma tu as plusieurs favoris stockés dans un seul champ. Tu as donc une relation One-to-One entre les membres et la "table de pivot", et aucune relation entre cette "table de pivot" et les favoris. C'est d'autant plus difficile de supprimer un article, car il faut bien sûr supprimer tous les favoris qui y sont associés. Beaucoup plus facile avec un schéma dans les règles.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
à la fin de tes requêtes, pour libérer un peu dans chaque requête et contrôle et sécurise la validité de tout ce que tu utilise à l'intérieur d'une requête, ne fait JAMAIS confiance à ce qui provient d'un utilisateur.