Pokračujeme v seriálu o redakčním systému. Dnes probereme indexový skript návštěvnické části redakčního systému a pár dalších drobností, které budou potřeba pro zobrazení stránek návštěvníkům.
V tomto díle seriálu o redakčním systému Vám popíši skript index.php, který se bude starat o zobrazení seznamu článků a to buďto všech, nebo jen článků v konkrétní rubrice či konkrétního autora. Skript se pak bude dále starat o zobrazení samotného článku. Nejdříve si však popíšeme jeden zásah do skriptu function.php, který rozšíříme o novou funkci a zbrusu nový skript levy.php, který bude vkládan do hlavního skriptu a do skriptu forum.php, který si popíšeme v příštím díle.
Do skriptu function.php přidáme funkci odkazy.php, která bude sloužit k rozdělení seznamu článků do více stránek s předem určeným početem článků na stránce. Tyto stránky budou mezi sebou vzájemně provázány odkazy. Funkce se bude volat se třemi parametry. Jelikož tato funkce není s redakčním systémem plně svázána a nedávno byl na serveru zveřejněn článek s touto tématikou (Výpis seznamu po stránkách), nebudu její popis příliš protahovat. Pro pochopení funkce jsou v kódu komentáře. Funkce nám vrátí dvě důležité proměnné, a to: $odtud, která bude využita v hlavních SQL dotazech a proměnnou $odkazy, která bude obsahovat část HTML kódu s odkazy na další stránky seznamu…
// proměnná $pocet obsahuje počet nalezených záznmů v DB,
// $zpp je počet záznamů na stránce = $CL_PER_PAGE
// $url obsahuje základ url pro odkaz na další záznamy
// končí-li url nějakým předávaným parametrem uveďte na konec
// url adresy &, jinak url ukončete otazníkem
function odkazy($pocet,$zpp,$url)
{
global $odtud;
$odtud = 0;
// pokud je počet záznamů větší než počet záznamů na stránku,
// vytvoříme odkazy na další stránky
if ($pocet > $zpp)
{
// některé proměnné, které budeme používat
global $start,$odkazy;
$odkazy = '';
$starsi = 0;
$novejsi = 0;
$bufferek = 0;
$zbytek = $pocet % $zpp; // počet záznamů na poslední stránce
$bufferek = ($pocet - $zbytek) / $zpp; // počet stránek
// pokud je zbytek 0, bude počet stránek menší o 1
if ($zbytek == 0)
$bufferek--;
// pokud existuje proměnná $start, musíme spočítat
// které záznamy z databáze zobrazíme.
if ($start > 0)
{
// zaokrouklíme
$start = Round($start);
// idnex záznamu
$buffer = $start * $zpp;
// pokud je $buffer větší než $start, budeme
// zobrazovat poslední stránku
if ($buffer > $pocet)
$start = $bufferek;
}
// pokud $start neexsituje nastavíme jej na 0
else
{
$start = 0;
}
// od tohoto indexu výsledku databáze začneme zobrazovat
// data
$odtud = ($start * $zpp);
$odkazy = "<DIV ALIGN=CENTER><B>";
// pokud je uživatel na třetí stránce (číslováno od 0),
// bude vždy zobrazen odkaz na nejnovější záznamy
if ($start>1)
{
$odkazy .= "[ <A HREF=" . $url . "start=0>Nejnovější</A> ]";
$novejsi = 1;
}
// pokud je nastavena proměnná $start větší než 0, zobrazíme odkaz na
// novější záznamy
if ($start > 0)
{
// zobrazilo se už něco dříve, odkazy rozdělíme pomlčkou
if ($novejsi == 1)
$odkazy .= " - ";
$odkazy .= "[ <A HREF=" . $url . "start=" . ($start-1) . ">Novější</A> ]";
$novejsi = 1;
}
// je-li počet stránek rovný aktuální stránce+1, pak zobrazíme
// odkaz na starší záznamy
if (($start+1) <= $bufferek)
{
// zobrazilo se už něco dříve, odkazy rozdělíme pomlčkou
if ($novejsi == 1)
$odkazy .= " - ";
$odkazy .= "[ <A HREF=" . $url . "start=" . ($start+1) . ">Starší</A> ]";
$starsi = 1;
}
// je-li počet stránek větší než aktuální stránka+1, zobrazíme
// odkaz na nejstarší záznamy.
if (($start+1) < $bufferek)
{
// zobrazilo se už něco dříve, odkazy rozdělíme pomlčkou
if ($novejsi == 1 || $starsi == 1)
$odkazy .= " - ";
$odkazy .= "[ <A HREF=" . $url . "start=" . $bufferek . ">Nejstarší</A> ]";
}
// v proměnné odkazy budeme mít odkazy se stránkováním záznamů
$odkazy .= "</B></DIV>";
}
}
Dalším skriptem bude skript levy.php, který bude obsahovat levý sloupec stránky, jež bude využívat jak hlavní stránka, tak i stránky s diskuzemi ke článkům. Jeho strukturu jsem navrhl tak, aby zde byly všechny důležité informace – rubriky, seznam aktuálních a nejčtenějších článků, kráté zprávy a seznam autorků k rychlé volbě článků jednotlivých autorů. Samozřejmě, že uspořádání těchto informací je na vás, rozdělení nemusí vyhovovat všem. Jelikož se jedná o triviální kód (oproti předchozím skriptům), uvedu rovnou jeho komentovanou citaci:
levy.php (/levy.php)
<B>Rubriky:</B><BR>
<A HREF="index.php">Titulní stránka</A><BR>
<?
// vložíme seznam rubrik
include "./inc/rubriky";
?>
<BR>
<B>Aktuální články:</B><BR>
<TABLE BORDER="0">
<?
$cas = time();
// vybereme 5 nejnovějších článků. Článek musí být schválený
// a čas vydání musí být menší nebo shodný s aktuálním
@$sql = mysql_query("SELECT id,nadpis FROM clanky
WHERE stav = 'a' AND datum <= $cas
ORDER BY datum DESC LIMIT 0,5");
while ($data = mysql_fetch_row($sql))
{
// zobrazíme výsledek
?>
<TR>
<TD VALIGN="TOP">-</TD>
<TD VALIGN="TOP">
<A HREF="index.php?clanek=<? echo $data[0]; ?>"><? echo $data[1]; ?></TD>
</TR>
<?
}
@mysql_free_result($sql);
?>
</TABLE>
<BR>
<B>Nejčtenější články:</B><BR>
<TABLE BORDER="0">
<?
// vybereme 5 článků s nejvyšší čteností. Článek musí být schválený
// a čas vydání musí být menší nebo shodný s aktuálním
@$sql = mysql_query("SELECT id,nadpis FROM clanky
WHERE stav = 'a' AND datum <= $cas
ORDER BY counter DESC LIMIT 0,5");
while ($data = mysql_fetch_row($sql))
{
?>
<TR>
<TD VALIGN="TOP">-</TD>
<TD VALIGN="TOP">
<A HREF="index.php?clanek=<? echo $data[0]; ?>"><? echo $data[1]; ?></TD>
</TR>
<?
}
@mysql_free_result($sql);
?>
</TABLE>
<BR>
<B>Krátké zprávy:</B><BR>
<?
// vložíme krátké zprávy
include "./inc/kz";
?>
<BR>
<FORM METHOD="GET" ACTION="index.php">
<B>Články autora:</B>
<SELECT NAME="autor" ONCHANGE="submit();">
<OPTION VALUE="">Vyberte autora</OPTION>
<?
// vložíme seznam autorů
include "./inc/autori";
?>
</SELECT>
</FORM>
Nyní se dostáváme, pro návštěvníky serveru k nejdůležitějšímu skriptu, jimž je index.php, který se stará o zobrazení seznamu článků, řazených dle autorů či rubrik, dále pak se stará o zobrazení samotného článku. Začneme seznamy rubrik, které jsou celkem tři. Jeden je seznam všech článků a bude se zobrazovat na titulní stránce. Dále pak se jedná o seznam článků rozdělených do jednotlivých rubrik a článků rozdělených dle autorů. O vytovření takovéhoto seznamu se bude starat vždy jeden docela velký SQL dotaz. Každý bude mírně modifikován.
články na titulní stránce SELECT C.id,C.nadpis,C.anotace,C.datum, A.jmeno,A.id,count(F.id),R.id,R.rubrika FROM clanky C, rubriky R, autori A LEFT JOIN fora F ON F.id_clanku = C.id WHERE C.id_rubrika = R.id AND C.id_autor = A.id AND C.stav = 'a' AND C.datum <= $cas GROUP BY C.id ORDER BY C.datum DESC, C.priorita DESC LIMIT $odtud,$CL_PER_PAGE
články v rubrice SELECT C.id,C.nadpis,C.anotace,C.datum, A.jmeno,A.id,count(F.id) FROM clanky C, autori A LEFT JOIN fora F ON F.id_clanku = C.id WHERE C.id_rubrika = $rubrika AND C.id_autor = A.id AND C.stav = 'a' AND C.datum <= $cas GROUP BY C.id ORDER BY C.datum DESC, C.priorita DESC LIMIT $odtud,$CL_PER_PAGE
články autora SELECT C.id,C.nadpis,C.anotace,C.datum,R.id,R.rubrika, count(F.id) FROM clanky C, rubriky R LEFT JOIN fora F ON F.id_clanku = C.id WHERE C.id_rubrika = R.id AND C.id_autor = $autor AND C.stav = 'a' AND C.datum <= $cas GROUP BY C.id ORDER BY C.datum DESC, C.priorita DESC LIMIT $odtud,$CL_PER_PAGE
Každý SQL dotaz obsahuje totožné části, kterými je LEFT JOIN spojení s tabulkou fora, pomocí kterého vybereme z databáze i ten článek, který v diskuzi nemá žádný příspěvek. Vybíráme články které jsou schváleny C.stav = ‚a‘ a které už byly publikovány C.datum <= $cas. Další společnou část mají třídění C.datum DESC, C.priorita DESC (podle data a priority). Poslední je část LIMIT $odtud,$CL_PER_PAGE, která slouží k selectu jen určitého počtu článků, které budou na jedné stránce seznamu zobrazeny. Mění se pouze selectované položky a případně i tabulky ze kterých se data tahají (jedná-li se o seznam článků v konkrétní rubrice, pak nepotřebujeme znát rubriku, ve které je článek vystaven, pokud vybíráme články dle jednotlivých autorů, nemusíme znát informace o autorovi).
Každý z výše uvedených SQL dotazů předchází SQL dotaz kratší, který spočítá buď počet všech článků, počet článků autora nebo počet článků v rubrice (záleží na tom co budeme zobrazovat). Do součtu jsou zařazovány pouze články, které jsou schváleny a jejich čas publikace je stejný nebo nižší než aktuální. Výsledek tohoto dotazu bude sloužit k rozpočítání hlavního výsledku do více stránek tak, aby se nezobrazoval seznam všech článků najednou na jedné stránce. Dalším selectem je select samotného článku, který jsme si popsali v minulém dílu seriálu. Tento dodaz bude opět mírně modifikován – přibyde do něj podmínka, která bude zobrazovat jen aktivní a publikované články.
index.php (/index.php)
<?
// vložíme soubory s funkcemi
include "./conn.php";
include "./function.php";
// zobrazíme hlavičku stránky
head();
?>
<TABLE BORDER="0" ALIGN="CENTER" WIDTH="100%">
<TR>
<TD VALIGN="TOP" WIDTH="200">
<!-- levý slopec -->
<?
// vložíme levý sloupec
include "./levy.php";
?>
<!-- levý slopec - konec -->
</TD>
<TD VALIGN="TOP">
<!-- pravý slopec -->
<?
// pokud existuje proměnná $clanek zobrazíme článek být schválený
// a čas vydání musí být menší nebo shodný s aktuálním
if ($clanek > 0)
{
// select článku. Článek musí být aktivní a musí
@$sql = mysql_query("SELECT C.nadpis,A.jmeno,A.email,R.rubrika,
C.datum,C.anotace,C.clanek,A.oautorovi
FROM clanky C, rubriky R, autori A
WHERE C.id_autor = A.id AND C.id_rubrika = R.id
AND C.stav = 'a' AND datum <= $cas
AND C.id = $clanek");
// pokud nalezneme v databízi jeden záznam, zobrazíme článek
if (mysql_num_rows($sql) == 1)
{
$data = mysql_fetch_row($sql);
// přičteme počítadlo přečtení
@$sql = mysql_query("UPDATE clanky SET counter = counter + 1
WHERE id = $clanek");
// spočítáme příspěvky v diskuzi
@$sql = mysql_query("SELECT count(*) FROM fora
WHERE id_clanku = $clanek");
$prispevku = mysql_result($sql,0,0);@mysql_free_result($sql);
// zobrazíme článek
?>
<H3 ALIGN=“CENTER“><? echo $data[0]; ?></H3>
<? echo $data[6]; ?>
<P>
Publikováno: <B><? echo date(„d.m.Y“,$data[4]); ?></B>
v rubrice <B><? echo $data[3]; ?></B>.
<BR>
<B>Diskuze:</B>
<A HREF=“forum.php?clanek=<? echo $clanek; ?>“>
<?
// pokud v diskuzi není příspěvek
if ($prispevku == 0)
{ echo „žádný příspěvek“; }
// pokud je v diskuzi jeden příspěvek
elseif ($prispevku == 1)
{ echo „jeden příspěvek“; }
// pokud jsou v diskuzi 2,3 nebo 4 příspěvky
elseif ($prispevku > 1 && $prispevku < 5)
{ echo $prispevku . „příspěvky“; }
// pokud je v diskuzi více než 4 příspěvky
else
{ echo $prispevku . „příspěvků“; }
?>
</A><BR>
<B>Autor:</B> <A HREF=“mailto:<? echo $data[2]; ?>“>
<? echo $data[1]; ?></A>
</P>
<P><? echo $data[7]; ?></P>
<?
}
// pokud v databázi nenalezneme žádný článek
else
{
?><H1 ALIGN=“CENTER“>Článek neexistuje !!!</H1><?
}
}
// pokud existuje proměnná $rubrika zobrazíme články rubriky
elseif ($rubrika > 0)
{
@$sql = mysql_query(„SELECT * FROM rubriky WHERE id = $rubrika“);
if (mysql_num_rows($sql) == 1)
{
@$data = mysql_fetch_row($sql);
?><H3 ALIGN=“CENTER“>Rubrika
<? echo $data[1]; ?></H3><?
// select přehledu článků
@$sql = mysql_query(„SELECT count(*) FROM clanky
WHERE stav = ‚a‘ AND datum <= $cas
AND id_rubrika = $rubrika
ORDER BY datum DESC, priorita DESC“);
// pokud je v databázi alespoň jeden článek
if (mysql_result($sql,0,0) > 0)
{
odkazy(mysql_result($sql,0,0),$CL_PER_PAGE,
„index.php?rubrika=“.$rubrika.“&“);
// select přehledu článků
@$sql = mysql_query(„SELECT C.id,C.nadpis,C.anotace,C.datum,
A.jmeno,A.id,count(F.id)
FROM clanky C, autori A
LEFT JOIN fora F ON F.id_clanku = C.id
WHERE C.id_rubrika = $rubrika AND C.id_autor = A.id
AND C.stav = ‚a‘ AND C.datum <= $cas
GROUP BY C.id
ORDER BY C.datum DESC, C.priorita DESC
LIMIT $odtud,$CL_PER_PAGE“);
// pro každý záznam z databáze zobrazíme získaná data
while ($row = mysql_fetch_row($sql))
{
?>
<H3><A HREF=“index.php?clanek=<? echo $row[0]; ?>“>
<? echo $row[1]; ?></A></H3>
<DIV>
<? echo $row[2]; ?>
<BR>
<B>Publikováno:</B> <? echo date(„d.m.Y“,$row[3]); ?>.
<B>Autor</B>:
<A HREF=“index.php?autor=<? echo $row[5]; ?>“>
<? echo $row[4]; ?></A><BR>
<?
if ($row[6] > 0)
{
?>
<B>Diskuze:</B>
<A HREF=“forum.php?clanek=<? echo $row[0]; ?>“>
<?
// pokud je v diskuzi jeden příspěvek
if ($row[6] == 1)
{ echo „jeden příspěvek“; }
// pokud jsou v diskuzi 2,3 nebo 4 příspěvky
elseif ($row[6] > 1 && $row[6] < 5)
{ echo $row[6] . „příspěvky“; }
// pokud je v diskuzi více než 4 příspěvky
else
{ echo $row[6] . „příspěvků“; }
echo „</A>“;
}
?>
</DIV>
<?
}
echo „<BR>“.$odkazy;
@mysql_free_result($sql);
}
else
{
?><H1 ALIGN=“CENTER“>Nenalezeny žádné články !!!</H1><?
}
}
else
{
?><H1 ALIGN=“CENTER“>Rubrika neexistuje !!!</H1><?
}
}
// pokud existuje proměnná $autor zobrazíme články autora
elseif ($autor > 0)
{
@$sql = mysql_query(„SELECT * FROM autori WHERE id = $autor“);
if (mysql_num_rows($sql) == 1)
{
@$data = mysql_fetch_row($sql);
?>
<H3 ALIGN=“CENTER“>Autor:
<A HREF=“mailto:<? echo $data[4]; ?>“>
<? echo $data[3]; ?></A></H3>
<?
// select přehledu článků
@$sql = mysql_query(„SELECT count(*) FROM clanky
WHERE stav = ‚a‘ AND datum <= $cas
AND id_autor = $autor
ORDER BY datum DESC, priorita DESC“);
// pokud je v databázi alespoň jeden článek
if (mysql_result($sql,0,0) > 0)
{
odkazy(mysql_result($sql,0,0),$CL_PER_PAGE,
„index.php?autor=“.$autor.“&“);
// select přehledu článků
@$sql = mysql_query(„SELECT C.id,C.nadpis,C.anotace,C.datum,R.id,
R.rubrika,count(F.id)
FROM clanky C, rubriky R
LEFT JOIN fora F ON F.id_clanku = C.id
WHERE C.id_rubrika = R.id AND C.id_autor = $autor
AND C.stav = ‚a‘ AND C.datum <= $cas
GROUP BY C.id
ORDER BY C.datum DESC, C.priorita DESC
LIMIT $odtud,$CL_PER_PAGE“) or die(mysql_error());
// pro každý záznam z databáze zobrazíme získaná data
while ($row = mysql_fetch_row($sql))
{
?>
<H3><A HREF=“index.php?clanek=<? echo $row[0]; ?>“>
<? echo $row[1]; ?></A></H3>
<DIV>
<? echo $row[2]; ?>
<BR>
<B>Publikováno:</B> <? echo date(„d.m.Y“,$row[3]); ?>
v <B>rubrice</B>:
<A HREF=“index.php?rubrika=<? echo $row[4]; ?>“>
<? echo $row[5]; ?></A><BR>
<?
if ($row[6] > 0)
{
?>
<B>Diskuze:</B>
<A HREF=“forum.php?clanek=<? echo $row[0]; ?>“>
<?
// pokud je v diskuzi jeden příspěvek
if ($row[6] == 1)
{ echo „jeden příspěvek“; }
// pokud jsou v diskuzi 2,3 nebo 4 příspěvky
elseif ($row[6] > 1 && $row[6] < 5)
{ echo $row[6] . „příspěvky“; }
// pokud je v diskuzi více než 4 příspěvky
else
{ echo $row[6] . „příspěvků“; }
echo „</A>“;
}
?>
</DIV>
<?
}
echo „<BR>“.$odkazy;
}
else
{
?><H1 ALIGN=“CENTER“>Nenalezeny žádné články !!!</H1><?
}
}
else
{
?><H1 ALIGN=“CENTER“>Autor neexistuje !!!</H1><?
}
}
// jinak zobrazíme články ze všech rubrik i autorů.
else
{
?><H3 ALIGN=“CENTER“>Hlavní stránka</H3><?// select přehledu článků
@$sql = mysql_query(„SELECT count(*) FROM clanky
WHERE stav = ‚a‘ AND datum <= $cas
ORDER BY datum DESC, priorita DESC“);
// pokud je v databázi alespoň jeden článek
if (mysql_result($sql,0,0) > 0)
{
odkazy(mysql_result($sql,0,0),$CL_PER_PAGE,“index.php?“);
// select přehledu článků
@$sql = mysql_query(„SELECT C.id,C.nadpis,C.anotace,C.datum,
A.jmeno,A.id,count(F.id),R.id,R.rubrika
FROM clanky C, rubriky R, autori A
LEFT JOIN fora F ON F.id_clanku = C.id
WHERE C.id_rubrika = R.id AND C.id_autor = A.id
AND C.stav = ‚a‘ AND C.datum <= $cas
GROUP BY C.id
ORDER BY C.datum DESC, C.priorita DESC
LIMIT $odtud,$CL_PER_PAGE“);
// pro každý záznam z databáze zobrazíme získaná data
while ($row = mysql_fetch_row($sql))
{
?>
<H3><A HREF=“index.php?clanek=<? echo $row[0]; ?>“>
<? echo $row[1]; ?></A></H3>
<DIV>
<? echo $row[2]; ?>
<BR>
<B>Publikováno:</B> <? echo date(„d.m.Y“,$row[3]); ?>
v <B>rubrice</B>:
<A HREF=“index.php?rubrika=<? echo $row[7]; ?>“>
<? echo $row[8]; ?></A><BR>
<B>Autor</B>:
<A HREF=“index.php?autor=<? echo $row[5]; ?>“>
<? echo $row[4]; ?></A><BR>
<?
if ($row[6] > 0)
{
?><B>Diskuze:</B>
<A HREF=“forum.php?clanek=<? echo $row[0]; ?>“><?
// pokud je v diskuzi jeden příspěvek
if ($row[6] == 1)
{ echo „jeden příspěvek“; }
// pokud jsou v diskuzi 2,3 nebo 4 příspěvky
elseif ($row[6] > 1 && $row[6] < 5)
{ echo $row[6] . „příspěvky“; }
// pokud je v diskuzi více než 4 příspěvky
else
{ echo $row[6] . „příspěvků“; }
echo „</A>“;
}
?></DIV><?
}
echo „<BR>“.$odkazy;
@mysql_free_result($sql);
}
else
{
?><H1 ALIGN=“CENTER“>Nenalezeny žádné články !!!</H1><?
}
}
?>
<!– pravý slopec – konec –>
</TD>
</TR>
</TABLE>
<?
foot();
mysql_close($conn);
?>
Na závěr chci říci, že stálé selectování z databáze není nejlepší řešení, nicméně je nejjednoduchší k pochopení systému. Je jasné, že selectovat nejčtenější, nejnovější články, stejně jako seznamy rubrik je celkem neefektivní a v případě velké návštěvnosti serveru by mohlo docházet k přetížení serveru, pokud tedy myslíte, že bude zátěž velká, budete muset připrogramovat skripty, které budou generovat soubory obsahující právě tyto informace. Vše nechávám plně na vaší fantazii a schopnostech. Jen pro představu uvádím jeden zdroj inspirace. Skripty function.php, levy.php a index.php si můžete stáhnot v zazipovaném arcivu. V příštím a asi už posledním díle seriálu si probereme diskuzní fóra ke článkům a jejich generování.