Bessere Möglichkeit das Abzufragen?
E wie einfach
- php
0 Cheatah0 Vinzenz Mai0 E wie einfach0 ChrisB0 Vinzenz Mai
0 Tom0 Encoder
Hi, ich überprüfe mit folgender Funktion, ob ein User schon etwas gepostet hat, und verhindere so Spamming:
public function CompareIP() {
$IP = $_SERVER['REMOTE_ADDR'];
$IP = ip2long($IP);
$Date = time();
$DB_IP = mysql_query("SELECT IP,Date FROM test WHERE IP = '$IP'");
if(mysql_affected_rows() == 1) {
while($Row = mysql_fetch_assoc($DB_IP)) {
$CompareDate = $Row['Date'] + 300; // 5min
}
if($Date >= $CompareDate) {
return TRUE;
}
else {
return FALSE;
}
}
else {
// NOCH NICHT ENDGÜLTIG
return TRUE;
}
}
Zur Erklärung: Wenn die IP bereits in der DB gespeichert ist, wird verglichen, ob 300 Sekunden (5min) rum sind, so dass er wieder posten kann. Wenn nein (Bei // NOCH NICHT ENDGÜLTIG) soll er TRUE zurückgeben, da die IP nicht vorhanden ist, da der User noch nicht gepostet hat. Jetzt frage ich mich aber, ob ich das anders als mit "WENN NICHT GENAU EIN DATENSATZ ANGESPROCHEN WURDE" lösen kann. Denn dies ist ja auch der Fall, sollte ein Fehler wider Erwarten auftreten. Stellen wir uns mal vor, durch fehlerhafte Einträge findet er nichts und gibt nun nichts zurück, obwohl der user nicht posten dürfte. Was dann? Dann würde er genau 0 datensätze angesprochen haben, und gibt trotzdem Return TRUE zurück. Habt ihr da eine bessere Idee, wie man testen kann, ob der denn garnicht eingetragen ist?
Hi,
Jetzt frage ich mich aber, ob ich das anders als mit "WENN NICHT GENAU EIN DATENSATZ ANGESPROCHEN WURDE" lösen kann. Denn dies ist ja auch der Fall, sollte ein Fehler wider Erwarten auftreten.
stimmt. Allerdings ist die Anzahl der Beiträge, die den betreffenden Zeitraum mit der IP-Adresse umspannen, entweder 0, oder, sofern Du die Menge auf 1 limitierst, 1. Deine anschließende Datumsüberprüfung ist nicht mehr nötig - die Datenbank kann das hervorragend selbst.
Cheatah
Hallo,
Hi, ich überprüfe mit folgender Funktion, ob ein User schon etwas gepostet hat, und verhindere so Spamming:
das bezweifle ich.
public function CompareIP() {
$IP = $_SERVER['REMOTE_ADDR'];
$IP = ip2long($IP);
warum nicht einfach wie "E wie einfach"?
Warum wandelst Du die IP-Adresse um?
Warum speicherst Du sie nicht in einfacher, lesbarer Punkt-Notation?
$DB_IP = mysql_query("SELECT IP,Date FROM test WHERE IP = '$IP'");
if(mysql_affected_rows() == 1) {
Warum verwendest Du hier mysql_affected_rows()?
Warum verwendest Du nicht eine Abfrage, die schlicht und einfach eine einzige Zeile mit einer Spalte zurückliefert, die den gewünschten boolschen Wert enthält? Das wäre doch viel einfacher. MySQL hat alle notwendigen Funktionen eingebaut. Nutze sie.
Warum fehlt die Fehlerbehandlung?
Fragende Grüße
Vinzenz
das bezweifle ich.
So? Du kennst mein komplettes System nicht, es ist schon sicher. ;)
warum nicht einfach wie "E wie einfach"?
Mache ich doch. ;)
Warum wandelst Du die IP-Adresse um?
Varchar(15) würde wesentlich mehr speicher verbrauchen, als unsigned int(10), außerdem durch Indexierung nacher ein großer Geschwindigkeitsvorteil. Siehe http://phpperformance.de/ip-adressen-optimal-speichern/
Warum speicherst Du sie nicht in einfacher, lesbarer Punkt-Notation?
Siehe oben.
$DB_IP = mysql_query("SELECT IP,Date FROM test WHERE IP = '$IP'");
if(mysql_affected_rows() == 1) {Warum verwendest Du hier mysql_affected_rows()?
Warum verwendest Du nicht eine Abfrage, die schlicht und einfach eine einzige Zeile mit einer Spalte zurückliefert, die den gewünschten boolschen Wert enthält? Das wäre doch viel einfacher. MySQL hat alle notwendigen Funktionen eingebaut. Nutze sie.
Gut, ein Punkt für dich, das werde ich machen. Eine Simple Vereinfachung ...
Warum fehlt die Fehlerbehandlung?
Fehlt nicht, ist in den if und else Blöcken versteckt, die alle Möglichkeiten abfangen, oder meinst du etwas anderes?
Hi,
Warum fehlt die Fehlerbehandlung?
Fehlt nicht, ist in den if und else Blöcken versteckt, die alle Möglichkeiten abfangen, oder meinst du etwas anderes?
Das Absetzen der Query mittels mysql_query bzw. deren anschliessende Bearbeitung durch die DB kann aus verschiedensten Gründen fehlschlagen.
Du machst aber sofort danach mit einer Funktion weiter, die eine nur im Erfolgsfall vorhandene gültige MySQL-Ressourcenkennung erwartet.
MfG ChrisB
Hallo,
Warum wandelst Du die IP-Adresse um?
Varchar(15) würde wesentlich mehr speicher verbrauchen, als unsigned int(10), außerdem durch Indexierung nacher ein großer Geschwindigkeitsvorteil. Siehe http://phpperformance.de/ip-adressen-optimal-speichern/
optimiere kein Performance-Problem, das Du nicht hast.
Weiter:
a) Speicherplatz ist das allergeringste Problem, wenn es je IP-Adresse
gerade mal einen einzigen Eintrag gibt. Ganz besonders, wenn ich an
die regulären Inhalte je IP-Adresse denke, die sicher ein Vielfaches
dieses Platzes belegen.
b) bezweifle ich die Richtigkeit des Benchmarks:
Suchoperation auf einer indexierten Spalte benötigt genausolange
wie auf einer nicht indexierten Spalte. Da ist was faul! Und somit
das Fazit des Artikels hinfällig.
c) würde ich, wenn überhaupt, MySQL die Umwandlung übertragen.
Oh ja, und ein paar Byte mehr an die DB übermitteln. Aber gerne!
d) Gleichfalls würde ich das Erzeugen des Zeitstempels der DB überlassen
und dafür einen angemessenen Datentyp verwenden.
$DB_IP = mysql_query("SELECT IP,Date FROM test WHERE IP = '$IP'");
if(mysql_affected_rows() == 1) {Warum verwendest Du hier mysql_affected_rows()?
Was möchtest Du hier mit mysql_affected_rows() testen? Eine Operation, die in Deinem vorgestellten Code nicht vorkommt? Möchtest Du nicht eher mysql_num_rows() verwenden?
Warum verwendest Du nicht eine Abfrage, die schlicht und einfach eine einzige Zeile mit einer Spalte zurückliefert, die den gewünschten boolschen Wert enthält? Das wäre doch viel einfacher. MySQL hat alle notwendigen Funktionen eingebaut. Nutze sie.
Gut, ein Punkt für dich, das werde ich machen. Eine Simple Vereinfachung ...
Ja, wirf alles aus dem PHP-Code raus, was die DB machen kann. Du sparst zunächst 80% der Codezeilen ein und kannst Dich dann ...
Warum fehlt die Fehlerbehandlung?
Fehlt nicht, ist in den if und else Blöcken versteckt, die alle Möglichkeiten abfangen, oder meinst du etwas anderes?
... um die Fehlerbehandlung, wie von Chris skizziert, kümmern.
Freundliche Grüße
Vinzenz
Hello,
Hi, ich überprüfe mit folgender Funktion, ob ein User schon etwas gepostet hat, und verhindere so Spamming:
public function CompareIP() {
$IP = $_SERVER['REMOTE_ADDR'];
$IP = ip2long($IP);
$Date = time();$DB_IP = mysql_query("SELECT IP,Date FROM test WHERE IP = '$IP'");
if(mysql_affected_rows() == 1) {
while($Row = mysql_fetch_assoc($DB_IP)) {
$CompareDate = $Row['Date'] + 300; // 5min
}
if($Date >= $CompareDate) {
return TRUE;
}
else {
return FALSE;
}
}
else {
// NOCH NICHT ENDGÜLTIG
return TRUE;
}
}
Unabhängig von dem, was Vinzenz & Co. Dir schon geschrieben haben, ist das ja wohl nicht der vollständige Code?
Ich sehe hier nur ein Select-Statement. Wie kommen denn die Daten in die DB?
Du schreibst selber "... wenn Fehler auftreten ...". Ich bin der Meinung, den Fehler machst Du.
Eine Überprüfung per Select ist nicht möglich, wenn man die Tabelle nicht für das Select und das anschließende vermutlich notwendige Update/Insert (Replace) sperren will, sodass die beiden Operationen atomar gebunden werden.
Siehe: http://en.wikipedia.org/wiki/Time-of-check-to-time-of-use
Ohne Locks musst du also mit einem updatenden Statement mit geeigneter Where-Klausel abfragen, ob schon ein Eintrag vorhanden ist.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Noch was zur Denkweise an sich. Es gibt Foren (so wie dieses hier), wo man durchaus innerhalb von 5 Min. nochmal was schreiben will. Entweder eine schnelle Antwort, einen Nachtrag oder sowas. Wenn ich da dann 5 Min. warten muss, schreib ich halt was evtl. recht sinnvolles nicht. Wär doch schade drum.
Ein Spammer dagegen kommt gern nach 5 Minuten wieder.