Grundsatzfragen zur Programmierung eines Forums

lisali

Erfahrenes Mitglied
Hallo,

ich habe extra den allgemeinen Thread-Titel gewählt, weil ich mehrere Fragen habe.

Also, ich bin dabei ein Forum zu bauen und habe bisher auch alles vorerst notwendige.

Jedenfalls habe ich ganz am Anfang so eine ähnliche Übersicht wie hier im Forum. Ein Beispiel:

[Allgemein] (10 Foren, 4 Threads, 19 Beiträge)
- Support
- Neuigkeiten
[Programmierung] (x Foren, y Threads, z Beiträge)
- PHP
- Java

Dabei ist das in den eckigen Klammern jeweils die Foren-Kategorie. Jetzt habe ich aber meinen "alten" Code benutzt, wo ich noch nie mit SQL-Joins gearbeitet habe, deshalb mache ich da unglaublich viele SQL-Queries.

Im obigen Beispiel habe ich nämlich noch die Anzahl der Threads, Beiträge, Foren aufgelistet. Dafür habe ich jeweils immer eine mysql_num_rows-Abfrage benutzt. Also für jede EINZELNE Foren-Kategorie. Was wäre sinnvoller in dem Fall zu benutzen? UNION oder JOIN oder was ganz anderes, um die einzelnen Zahlen auszurechen und auszugeben?

Klickt man jetzt z.B. auf PHP, geht man in der Hierarchie eine Stufe runter und man sieht dann sozusagen [Programmierung] als Oberkategorie, dafür keine Anzahl der Foren mehr, aber Anzahl der Threads und Beiträgen.

Klickt man nun auf einen Thread geht es wieder eine Stufe runter und man sieht nur noch die Anzahl der Beiträge und die Beiträge selbst.

Was nun meine Frage ist, ist eigentlich "nur", wie viele Abfragen effizienterster Weise benötigt werden? Also, mit den wenigsten mit denen man in Hinsicht auf Performance auskommen könnte?
 
Zuletzt bearbeitet:
fetch_array kann nur einmal verwendet werden

Hallo,

ich hätte eine Frage zu meinem JOIN-Code, wo ich echt viele Joins mache, um die Beiträge anzuzeigen.
Also hier bin ich in einem Foren-Thread drin:

PHP:
if ($_GET['s'] == 'forum' && isset($_GET['bid']) && isset($_GET['tid']))
{
$query = mysql_query("SELECT 
ft.`id`, ft.`title`,ft.`uid`,ft.`icon`,ft.`hits`,
f.`name`,f.`about`,f.`sub_id`,
fp.`uid`,fp.`text`,fp.`date`,
u.`username`
FROM `forum_threads` AS ft 
LEFT JOIN `forum_posts` AS fp 
ON ft.`id` = fp.`tid`
LEFT JOIN `forum` AS f 
ON f.`sub_id` = ft.`sub_id`
LEFT JOIN `users` AS u 
ON fp.`uid` = u.`id`
WHERE ( ft.`id`='".$_GET['tid']."' )
ORDER BY fp.`id` DESC");

$forum = mysql_fetch_array($query);
mysql_query("UPDATE `forum_threads` SET `hits`=`hits`+1 WHERE `id`='".$_GET['tid']."'");

echo "<div><h1><a href='?s=forum&bid=".$_GET['bid']."sub_id=".$forum[`f`.sub_id]."'>".$forum['name']."</a></h1>
<br>".$forum['about']."<br><br></div><h1>".$forum['title']."</h1> (".$forum['hits']."x aufgerufen)<br><br>";	

echo comments($query);

Mit der Funktion comments() gebe ich die Beiträge aus, jedoch werden die Beiträge jeweils vierfach ausgegben. Liegt das etwa an den ganzen Joins oder am WHERE oder an was anderes?

An der Funktion comments() selbst kann es eigentlich nicht liegen, weil es nur eine while-Schleife ist und für die Formatierung der Beiträge auf der ganzen Seite zuständig ist.

Ich habe rausgefunden, dass die Extra-Anweisung mit dem fetch_array von $forum sozusagen die comments blockt. Jedenfalls entzieht er dann dem nächsten Fetch-Array, das durch comments() stattfindet einen Eintrag.
Kann mir jemand erklären wieso das so ist oder sollte ich für die Ausgabe, die keine Schleife benötigt (Thread-Titel, etc.), eine Extra-Query schreiben?
 
Vielen Dank, die Funktion kannte ich noch nicht!

Wenn ich bei der Foren-Übersicht bin und dort jeweils die Threads, Beiträge, Foren einer Foren-Kategorie zählen möchte, muss ich dazu echt 3 SQL-Abfragen schreiben?

Ich habe allesmögliche (wahrscheinlich falsch) versucht mit JOINS oder Union, aber ich komme nicht dahinter wie man das in eine SQL-Abfrage schafft. Ich möchte nicht so viele Abfragen senden und den Speicher so belasten.

Was kann ich da machen?

Edit:

So mache ich das nämlich:

PHP:
$rows = mysql_query("SELECT `id` FROM `forum` WHERE `sub_id`='".$sub['id']."'");
$num1 = mysql_num_rows($rows);
$rows = mysql_query("SELECT `id` FROM `forum_threads` WHERE `sub_id`='".$sub['id']."'");
$num2 = mysql_num_rows($rows);
$rows = mysql_query("SELECT `id` FROM `forum_posts` WHERE `sub_id`='".$sub['id']."'");
$num3 = mysql_num_rows($rows);

echo "<div class='fr'><h3>".$num1."</h3> Foren <h3>".$num2."</h3> Themen <h3>".$num3."</h3> Beitr&auml;ge</div>";
 
Zuletzt bearbeitet:
Wenn ich bei der Foren-Übersicht bin und dort jeweils die Threads, Beiträge, Foren einer Foren-Kategorie zählen möchte, muss ich dazu echt 3 SQL-Abfragen schreiben?
Bei einem halbwegs normalisierten Tabellenschema: ja.

Ich habe allesmögliche (wahrscheinlich falsch) versucht mit JOINS oder Union, aber ich komme nicht dahinter wie man das in eine SQL-Abfrage schafft. Ich möchte nicht so viele Abfragen senden und den Speicher so belasten.
Solang du nicht auf tatsächlich messbare Durchsatzprobleme wegen zu vieler Anfragen stößt, würde ich mir darüber keine Gedanken machen. Im Gegenteil: wenn man versucht, krampfhaft vollkommen unterschiedliche Abfragen über Joins zu kombinieren, kann das auch mal nach hinten los gehen und viel länger dauern als der einfache Ansatz. Die Anzahl der Abfragen ist nicht alles, viel wichtiger sind z.B. sinnvoll gesetzte Indizes.

So mache ich das nämlich:

PHP:
$rows = mysql_query("SELECT `id` FROM `forum` WHERE `sub_id`='".$sub['id']."'");
$num1 = mysql_num_rows($rows);
$rows = mysql_query("SELECT `id` FROM `forum_threads` WHERE `sub_id`='".$sub['id']."'");
$num2 = mysql_num_rows($rows);
$rows = mysql_query("SELECT `id` FROM `forum_posts` WHERE `sub_id`='".$sub['id']."'");
$num3 = mysql_num_rows($rows);

echo "<div class='fr'><h3>".$num1."</h3> Foren <h3>".$num2."</h3> Themen <h3>".$num3."</h3> Beitr&auml;ge</div>";
Es ist immer gut, wenn man der Datenbank genau mitteilt, was man möchte. In diesem Fall bist du nur an der Anzahl der Zeilen interessiert, die ein bestimmtes Kriterium erfüllen. Stattdessen fragst du hier aber nach der Spalte id, die dich eigentlich überhaupt nicht interessiert. Mach es stattdessen besser explizit, was du wissen willst:
PHP:
$result = mysql_query("SELECT COUNT(*) FROM `forum` WHERE `sub_id`='".$sub['id']."'");
$row = mysql_fetch_row($result);
$num1 = $row[0];
// etc.

Grüße,
Matthias
 
Zurück