Je suis en train de faire un petit forum en PHP et MySQL et j'aimerais bien inclure des bases de données pour faire un cooldown.
Par exemple que quelqu'un ne puisse pas créer un autre sujet avant 5 minutes, un autre message avant 15 secondes.
J'imagine que le formulaire doit vérifier dans la base de donnés si l'IP n'est pas présente, mais il faut que la base de données supprime automatiquement chaque IP plus vielle que 5 minutes ou 15 secondes (suivant la table).
Comment faire ça ?
Dans ta base de données, tu dois certainement pouvoir récupérer le dernier sujet créé par un utilisateur ?
Peut être même que tu peux récupérer directement le datetime du dernier sujet créé, sinon, je te conseil de stocker ce genre d'info dans ta BDD.
Ensuite, tu n'as plus qu'à récupérer la date courante avec PHP, et la comparer la date du dernier sujet créé.
perso, je garderai dans la table la date de dernier access, et je ferais la comparaison de temps manuellement avec une clause WHERE. Et seulement periodiquement (toute les heures ou tous les jours), je ferai la passe de menage qui vire les vielles entrees.
Tu es obligé d'utiliser ta base MySQL pour ça ? Pour moi c'est pas le plus adapté pour ce type de trucs. Si oui, utilise la méthode de Godrik. Sinon, utilise plutôt une base qui offre un mécanisme de TTL, Redis par exemple. A titre perso je partirais clairement sur cette deuxième solution, même si ça complexifie un peu ta stack.
Alors déjà avant de répondre, il faut tout d'abord préciser que ton approche n'est pas la bonne.
Première erreur : il ne faut en aucun cas associer une IP à un utilisateur car celle-ci est correspond à une connexion qui peut être partagée entre plusieurs utilisateurs (via un wifi public, un pc / une box familiale etc) ou même elle peut être tout simple dynamique .. bref, il faut éviter et plutôt faire ce genre d'opération avec des sessions/users.
Deuxième erreur : par rapport à ton problème, à savoir un forum, tu ne sembles pas avoir assez de recul par rapport aux données que tu vas stocker. As-tu fait un modèle de la base de donnée ? Si non je te conseille de le faire en réfléchissant bien. En effet, sur un forum tu devras souvent pour ne pas dire tout le temps enregistrer la date à laquelle nouveau message/topic a été posté. De ce fait, tu as suffisamment d'informations pour pouvoir faire ta vérification sans avoir besoin de recréer une autre table et encore moins d'avoir à faire une purge.
=> en gros, il te suffira de récupérer la date de création du dernier topic/message d'un utilisateur et de le comparer avec la date actuelle pour statuer s'il a la possibilité de créer un topic/message à cet instant.
Donc +1 TheRealMarco, les autres vos conseils ne sont pas très pertinents :
- godrik tu pars tête baissée dans une solution peu réfléchie plutôt que rappeler les bonnes pratiques (ip + redondance de l'information)
- WatchItBurn tu donnes des alternatives qui sont peu adaptées pour un néophyte, dur à gérer à son niveau ,de plus il est à 99.9% sur un hébergement mutualisé qui n'offre rien de mieux que mySQL
C'est pas nécessairement une mauvaise pratique la redondance dans une base relationnelle, parfois casser la normalisation est une simplification qui a un vrai intérêt. Là ça en a un car le TTL c'est un cas d'usage parallèle au reste des données, c'est du cache, d'où ma proposition d'utiliser un Redis, qui serait la solution retenue sur la plupart des vrais projets. Si toutefois on choisissait de l'implémenter sur une base relationnelle à la MySQL, on préférerait dénormaliser plutôt que de choisir la solution normalisée "naïve" (je dis "naïve" entre guillemets car c'est pas la solution naïve, c'est la solution engineerée, mais elle se trouve mal taillée en pratique) pour deux raisons :
Donc ouais, utiliser l'IP pour ça c'est une mauvaise idée je suis d'accord, mais ta solution et celle de TheRealMarco n'est pas suffisante non plus (il manque le nettoyage périodique évoqué par Godrik, qui peut être fait dans MySQL avec un scheduler par exemple) mais même carrément mauvaise selon moi, car "naïve" dans le sens où elle présuppose un environnement abstrait parfait, ce qui n'est pas la vraie vie.
Le 05 décembre 2016 à 20:52:37 WatchItBurn a écrit :
C'est pas nécessairement une mauvaise pratique la redondance dans une base relationnelle, parfois casser la normalisation est une simplification qui a un vrai intérêt. Là ça en a un car le TTL c'est un cas d'usage parallèle au reste des données, c'est du cache, d'où ma proposition d'utiliser un Redis, qui serait la solution retenue sur la plupart des vrais projets. Si toutefois on choisissait de l'implémenter sur une base relationnelle à la MySQL, on préférerait dénormaliser plutôt que de choisir la solution normalisée "naïve" (je dis "naïve" entre guillemets car c'est pas la solution naïve, c'est la solution engineerée, mais elle se trouve mal taillée en pratique) pour deux raisons :
- comme je le dis, c'est un usage parallèle au reste de la base, qui n'a rien à foutre dedans normalement, du coup on va vouloir éviter de polluer le reste des données pures avec des données techniques (dénormaliser pour garder la modélisation pure donc)
- encore une fois c'est du cache, en dénormalisant le jeu de données dans une table séparée (en key-value par exemple : [user ID/timestamp du dernier post]) on s'évite des requêtes régulières sur les tables de données. C'est con de parcourir la table "topics" en entier pour trouver la date du dernier post d'un user si on peut accéder à cette info directement en O(1) dans la table qui fait office de cache.
Donc ouais, utiliser l'IP pour ça c'est une mauvaise idée je suis d'accord, mais ta solution et celle de TheRealMarco n'est pas suffisante non plus (il manque le nettoyage périodique évoqué par Godrik, qui peut être fait dans MySQL avec un scheduler par exemple) mais même carrément mauvaise selon moi, car "naïve" dans le sens où elle présuppose un environnement abstrait parfait, ce qui n'est pas la vraie vie.
Je suis à 100% d'accord avec tes arguments , j'utilise beaucoup Redis en parallèle à une BDD relationnelle . Ce n'est pas sur le plan technique que je ne suis pas d'accord avec toi. Mais il ne pourra pas la mettre en place car il n'a pas le niveau : faire un forum php/mysql c'est un cas d'école pour s'entrainer, apprendre et son hébergement ne laissera pas de flexibilité quant au choix de la BDD. C'est justement parce que c'est un "faux" projet que ce n'est pas valable et non pas une vérité générale.
Par contre, là où je suis en désaccord c'est avec le fait de nettoyer, tu n'as pas besoin puisque que tu n'ajoutes pas de données, tu utilises uniquement celles qui existent et sont nécessaires au fonctionnement d'un forum.
Je suis complètement d'accord aussi sur le fait de lui proposer plutôt la solution de gestion manuelle de l'expiration en soi, c'est probablement là-dessus qu'il partira de toute façon Mais si plus tard il décide d'aller plus loin, ou qu'il veut voir un peu d'autres horizons, ça peut être intéressant pour lui d'avoir une suggestion alternative plus complexe mais plus efficace et moins compliquée. Même si son hébergement est gratuit, faire du Redis en local c'est à la portée de tout le monde.
Par contre, là où je suis en désaccord c'est avec le fait de nettoyer, tu n'as pas besoin puisque que tu n'ajoutes pas de données, tu utilises uniquement celles qui existent et sont nécessaires au fonctionnement d'un forum.
Si tu fais une requête sur la table "topics" à chaque fois qu'un utilisateur poste effectivement il n'y a pas de nettoyage à faire. Le nettoyage c'est plutôt à faire si on casse la normalisation et qu'on introduit une table qui fait office de cache (ce que je conseillerais dans tous les cas, cf mon deuxième point dans mon message précédent). Le nettoyage est nécessaire pour éviter que la table ne grossisse (ça grossira pas au delà du nombre d'utilisateurs mais bon, autant faire les choses bien)
- godrik tu pars tête baissée dans une solution peu réfléchie plutôt que rappeler les bonnes pratiques (ip + redondance de l'information)
Je ne suis pas bien d'accord avec ca.
La question de multiples utilisateurs par IP est un probleme de policy au niveau du site web plutot qu'un veritable probleme technique. C'est une solution raisonnable qui est deploye dans plein de systeme. fail2ban fait ca par IP par exemple.
Apres la redondance de l'information est en fait une bonne chose, tu as besoin de beaucoup moins d'information a lire/ecrire pour faire ta verification que si tu regarde toute la base. En plus les problemes classique lie a duplication de donnee ne sont pas un vrai probleme ici parceque tu n'as pas un vrai besoin de coherence.
Il n'y a pas d'identification obligatoire et je veux quand même un cooldown pour les gens qui postent en invité donc je me base sur l'IP.
Une approche simple pour ça :
Quand un utilisateur poste :
- Tu regardes si une variable de session 'lastMessage' existe.
Si elle existe :
- Tu compares cette variable avec la date actuelle. Si ton 'cooldown' est passé, tu postes et tu mets à jour la variable de session. SINON, tu empêches le message.
Plus d'infos sur les var de sessions : http://php.net/manual/fr/reserved.variables.session.php