Schleifen-Problem |
Maniac_81
PHP Profi
Dabei seit: 27.06.06
Beiträge: 2.087
Fähigkeiten: WBB3 Anfänger; WBB2 Profi Herkunft: localhost/ Forenversion: 2.3; Lite 2.0
|
|
Ich habe mir einen Hack gebaut, der die Userbeiträge bearbeitet. Nun macht es aber nicht das was ich genau möchte, scheint ein problem in den Schleifen zu sein:
Das ist der Auszug aus der acp/otherthuff.php
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
|
list($minzeichen) = $db->query_first("SELECT wert FROM bb".$n."_minzeichen WHERE id=1");
$result = $db->query("SELECT userid FROM bb".$n."_users ORDER BY userid ASC", $perpage, $perpage * ($page - 1));
while ($row = $db->fetch_array($result)) {
$db->query_first("UPDATE bb".$n."_users SET userposts=0 WHERE userid=".$row['userid']);
$result = $db->unbuffered_query("SELECT message FROM bb".$n."_posts WHERE userid=".$row['userid']);
while($data = $db->fetch_array($result)) {
if (wbb_strlen($data['message']) >= $minzeichen)
{
$db->unbuffered_query("UPDATE bb".$n."_users SET userposts = userposts + 1 WHERE userid = ".$row['userid']);
}
}
}
refresh("otherstuff.php?sid=$session[hash]&action=userposts&perpage=$perpage&page=".($page + 1), $lang->items['LANG_ACP_OTHERSTUFF_USERPOSTS'], round($page * $perpage / $totalcount * 100)."&on_off=1");
} |
|
Eigentlich sollte die 1. Schleife die userposts auf 0 setzen und die posts auslesen - das funktioniert.
in der 2. Schleife soll dann überprüft werden ob die die posts eine bestimmte länge haben, wenn ja dann userposts +1, das funktioniert auch!
was aber nicht funktioniert, das das mit allen Usern gemacht wird. Es wird nur ein user abgearbeitet, folglich stimmt was mit den schleifen nicht.
Es sind mehrere User angelegt und haben auch verschiedene beitragslängen.
Edit: Fehler gefunden......und dafür hab ich 2 Tage gesucht.....hätte mich lieber mal ausschlafen sollen.....lol
__________________ zufrieden mit meinem Support? dann hier bitte bewerten!
Sie haben 3 gelbe Bananen gewählt!
ÄPFEL! 3!!!
|
|
29.05.09 09:20 |
E-Mail
WWW
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Ääähm tschuldigung, aber das ist grottig. Du sendest SQL Queries in sogar VERSCHACHTELTEN while schleifen? Schlimmer gehts nimmer.
|
|
29.05.09 13:16 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Ich kenne die Tabellenstruktur des WBB 2 nicht, daher mal ein wenig pseudocodisch:
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
|
list($minzeichen) = $db->query_first("SELECT wert FROM bb".$n."_minzeichen WHERE id=1");
$sql = "SELECT user.userid, post.message
FROM bb".$n."_users user
LEFT JOIN bb".$n."_posts post
ON (user.userid = post.userID)
ORDER BY userid ASC";
/*
* What's the point in only grabbing the users and post for a certain page-no?
* Do you want to update them per page? A lot of clicking :P
*/
$result = $db->query($sql, $perpage, $perpage * ($page - 1));
$userData = array();
while ($row = $db->fetch_array($result)) {
// init the user record
if (!isset($userData[$row['userid']])) $userData[$row['userID']] = 0;
if (wbb_strlen($row['message']) >= $minzeichen) {
$userData[$row['userID']]++;
}
}
$inserts = '';
foreach ($userData as $userID => $userposts) {
if (!empty($inserts)) $inserts .= ',';
$inserts .= '('.$userID.', '.$userposts.')';
}
// INSERT INTO ... DUPLICATE KEY should work well or updating all rows here. Just make sure that userid is primary or unique
$sql = "INSERT INTO bb".$n."_user
(userid, userposts)
VALUES
".$inserts."
ON DUPLICATE KEY UPDATE userposts = VALUES(userposts)";
$db->query($sql);
refresh("otherstuff.php?sid=$session[hash]&action=userposts&perpage=$perpage&page=".($page + 1), $lang->items['LANG_ACP_OTHERSTUFF_USERPOSTS'], round($page * $perpage / $totalcount * 100)."&on_off=1"); |
|
Achtung. Das Feld userid in bbx_users muss einen PRIMARY oder UNIQUE Index haben.
Dieser Ansatz verbraucht jetzt lediglich 2 Queries für die Operation. Plus 1 Query für den Optionswert (das ist im WBB 3 vieeeeeeeel besser gelöst).
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von Hawkes: 29.05.09 14:28.
|
|
29.05.09 14:08 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Ersetze bei wbb_strlen das $data noch durch $row. Copy&Paste Fehler.
Ansonsten bin ich schon zu sehr an die WCF Codeguidelinesg gewöhnt xD
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
|
list($minzeichen) = $db->query_first("SELECT wert FROM bb".$n."_minzeichen WHERE id=1");
$sql = "SELECT user.userid, posts.message
FROM bb".$n."_users user
LEFT JOIN bb".$n."_posts post
ON (user.userid = post.userID)
ORDER BY userid ASC";
/*
* What's the point in only grabbing the users and post for a certain page-no?
* Do you want to update them per page? A lot of clicking :P
*/
$result = $db->query($sql, $perpage, $perpage * ($page - 1));
$userData = array();
while ($row = $db->fetch_array($result)) {
// init the user record
if (!isset($userData[$row['userid']])) $userData[$row['userid']] = 0;
if (wbb_strlen($row['message']) >= $minzeichen) {
$userData[$row['userid']]++;
}
}
$inserts = '';
foreach ($userData as $userID => $userposts) {
if (!empty($inserts)) $inserts .= ',';
$inserts .= '('.$userID.', '.$userposts.')';
}
// INSERT INTO ... DUPLICATE KEY should work well or updating all rows here. Just make sure that userid is primary or unique
$sql = "INSERT INTO bb".$n."_user
(userid, userposts)
VALUES
".$inserts."
ON DUPLICATE KEY UPDATE userposts = VALUES(userposts)";
$db->query($sql);
refresh("otherstuff.php?sid=$session[hash]&action=userposts&perpage=$perpage&page=".($page + 1), $lang->items['LANG_ACP_OTHERSTUFF_USERPOSTS'], round($page * $perpage / $totalcount * 100)."&on_off=1"); |
|
Probiers nochmal
|
|
29.05.09 14:39 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Welchen Datentyp hat denn userid im WBB2? Aus irgendeinem Grund scheinen da leere Strings (=NULL?) anstatt einer userID zurückzukommen.
Dafür kenne ich aber das WBB 2 zu wenig.
Das Vorhaben ist generell folgendes:
1. Verwende ein sinnloses Query um alle userIDs und postMessages zubekommen. Das Ganze sollte auch ohne JOIN gehen fällt mir gerade auf. Ich bin nur von deinen vielen Queires verwirrt gewesen
php: |
1:
|
$sql = "SELECT userid, message FROM bb".$n."_posts ORDER BY userid ASC"; |
|
2. Lege ein Array an, in dem für alle Benutzer der Postcounter gezählt wird.
3. Prüfe ob ein Post lang genug ist und wenn ja erhöhe den Postcounter des users um 1.
4. Baue mit einer for schleife INSERT Blöcke für ein SQL Query. Jeder Insert-Block besteht aus userid, userposts
5. Sende ein INSERT ... ON DUPLICATE KEY UPDATE query auf die usertabelle ab und nutze hierbei aus, dass bei dieser SQL Syntax bestehende Datensätze einfach aktualisiert werden ohne für jeden Datensatz ein extra Query zu verwenden.
|
|
29.05.09 14:53 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Huh?
Also kp was das WBB 2 macht, aber das erste Query muss ein Resultset liefern, dass die userid und den Inhalt des Posts liefert. Kp wie die Felder im WBB 2 heißen. Wenn der für message 1,2,3,4 usw. zurückliefert, dann ist message wohl nicht das Feld, dass den Text enthält.
Ein JOIN ist einfach eine Tabellenverknüpfung anhand eines Feldes, dass in 2 Tabellen jeweils vorhanden ist.
|
|
29.05.09 15:10 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Das Query muss aber wieder zurück. Das ist so falsch. Außerdem schreibt man keine PHP Variablen mehr in die Strings rein. Das zu evaluieren dauert auch bei PHP 5 immer noch länger als ein zusammengesetzer String. Bei PHP 4 hat man sogar 30% Performancegewinn.
|
|
29.05.09 17:01 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Ich hab gleich mal Zeit. Muss mir das Ding nur einbauen (Jaja Paketinstallationen sind was feines
)
Nur mal so zur Erklärung: Für mein Forum, dass ein sehr kleines ist (gerade mal 5700 Beiträge und 530 Mitglieder) würde dieses Script etwa 6700 Queries abschicken, wenn es die Neuberechnung für alle Benutzer macht. Dabei ist die Berechnung und Hochzählung eine Sache für PHP und nicht MySQL. Durch die Übermittelungszeiten und alles was so abläuft, wenn man ein Query an einen SQL Server schickt, ist das hier ein Performanceburner schlecht hin und wenn das Ganze nicht portionsweise ausgeführt werden würde, wäre das wohl ideal, um einen SQL Server mit nem DOS in die Knie zu zwingen.
EDIT:
Also... himmelkreuzgranatenhallelujaundachkp seid ihr sicher, dass ihr das WBB 2 angenehmer, intuitiver und benutzerfreundlicher findet? Allein der Hackeinbau war ein Graus und das ACP gibt einem dann den Rest.
Nunja. Wie auch immer: Ich habe in der otherstuff.php deinen Code durch meinen ersetzt und das funktioniert dann auch und verbraucht wie gesagt pro Zyklus nur 2 Queries, was extrem performant und datenbankschonend ist.
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
|
}elseif($on_off == 2){
$result = $db->query("SELECT userid, message FROM bb".$n."_posts ORDER BY userid ASC", $perpage, $perpage * ($page - 1));
$userData = array();
while ($row = $db->fetch_array($result)) {
// init the user record
if (!isset($userData[$row['userid']])) $userData[$row['userid']] = 0;
if (wbb_strlen($row['message']) >= $minzeichen) {
$userData[$row['userid']]++;
}
}
$inserts = '';
foreach ($userData as $userID => $userposts) {
if (!empty($inserts)) $inserts .= ',';
$inserts .= '('.$userID.', '.$userposts.')';
}
// INSERT INTO ... DUPLICATE KEY should work well or updating all rows here. Just make sure that userid is primary or unique
$sql = "INSERT INTO bb".$n."_user
(userid, userposts)
VALUES
".$inserts."
ON DUPLICATE KEY UPDATE userposts = VALUES(userposts)";
$db->query($sql);
refresh("otherstuff.php?sid=$session[hash]&action=userposts&perpage=$perpage&page=".($page + 1), $lang->items['LANG_ACP_OTHERSTUFF_USERPOSTS'], round($page * $perpage / $totalcount * 100));
} |
|
Hoffe du kommst so weiter. Was ich dazu sagen muss: Ich habe das natürlich mit PHP 5.2.9 und MySQL 5.1.34 verwendet. Es kann sein, dass sich in PHP 4 irgendwas anders verhält als in PHP 5, was zu dem falschen Eintrag führt. Da müsste ich aber, falls es denn bei dir überhaupt noch Fehler gibt, nochmal nachlesen. Ich habe erst vor 1 1/2 Jahren mit PHP angefangen und da dann natürlich mit PHP 5 und selbst das hat schon genug Macken, da kann ich mich mit all denen von PHP 4 nicht auskennen^^
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Hawkes: 02.06.09 22:14.
|
|
02.06.09 21:36 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Darüber steht aber der Grundsatz: Lieber einmal lang als mehrfach kurz.
Was deine Variante gemacht hat, war für jeden Beitrag einzeln ein Query an die DB zu schicken und den postCounter um eins zu erhöhen, anstatt einfach nur in PHP eine Variable hoch zu zählen.
Meines erachtens, sollte PRO Query soviel wie Möglich an Vorarbeit durch die Datenbank übernommen werden, also Gruppierungen, Berechnungen und Sortierungen, da hier SQL schneller ist als PHP. Aber in diesem Fall ist diese Art von Berechnung ganz klar ein Fall für PHP. Außerdem haben wir bei der WBB 3 Entwicklung auch den Grundsatz, dass ein Query niemals in einer Schleife zu stehen hat (mit Ausnahmefällen).
|
|
03.06.09 09:44 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Joa ich hab mal kurz wegen dieser Art der Verwendung von INSERT... ON DUPLICATE KEY UPDATE gegooglet, aber das scheint MySQL 4.1 auch zu können.
Also klar bei der WBB 3 Entwicklung kommt man mit einfachem PHP Code und Scriptbits, die man mal hier mal da einfügt nichtmehr hin, aber es stehen einem so viel mehr Möglichkeiten zur Verfügung und alles wirkt nochmals deutlich ausgereifter und intuitiver. Ich hab gestern Abend noch ein wenig mit dem ACP des WBB 2 gespielt. Da liegen wirklich welten zwischen WBB 2 und WBB 3. Auch fehlen dem WBB 2 einige administrative Funktionen.
|
|
03.06.09 11:39 |
Finden
Als Freund hinzufügen
|
|
|