V minulém dílu našeho seriálu jsme se zabývali otázkou výběru dat z
MySQL pomocí příkazu SELECT. Umět data správně vybrat není ale to
jediné - my je musíme uživateli rovněž v nějaké čtivé podobě
naservírovat. Dnes si ukážeme, jak na to.
Stránkujeme
Zkuste na chvíli zavzpomínat na předchozí díl našeho seriálu. Tam
jsme
si pořídili databázi všech obcí a jejich PSČ v České republice. Dejme
tomu, že budeme chtít všechny obce a jejich PSČ nějak vypsat. Asi
první, co Vás napadne, bude:
<?
// zde je include souboru s
konstantami
mysql_connect(SQL_HOST, SQL_USERNAME, SQL_PASSWORD);
mysql_select_db(SQL_DBNAME);
$vysledek=mysql_query("select * from psc");
while ($zaznam=MySQL_Fetch_Array($vysledek)) echo $zaznam["obec"]." ".$zaznam["psc"]."<BR>\n";
?>
a jistě by to fungovalo, ovšem narážíme zde na vážné problémy s
výkonem. Tabulka obcí má totiž více než 16000 řádků. Kdybyste něco
takového napsali a zkusili spustit, může dojít k následujícím problémům:
- Podstatně zatížíte databázi. Vrácení 16000 záznamů přece jen
nějakou
dobu potrvá.
- Co je horší, výsledná stránka bude mít téměř půl megabajtu.
Člověku s modemem se bude natahovat déle než minutu.
- V závislosti na nastavení webového serveru a/nebo PHP může být
rovněž překročena maximální doba pro běh skriptu a ten bude přerušen.
Podobným lapáliím se můžeme vyhnout, jestliže budeme výpisy výsledné
sady záznamů stránkovat. Naštěstí MySQL obsahuje šikovné rozšíření
příkazu SELECT, které nám umožní vrátit část sady záznamů danou prvním
řádkem a počtem. S úspěchem používám následující kód:
<?
define ("ROWS", 50);
if (!isset($_GET["celkem"])) //pokud nevíme,
kolik bude záznamů tak to zjistíme...
{
$vysledek=mysql_query("select count(*) as
pocet from psc");
$zaznam=mysql_fetch_array($vysledek);
$celkem=$zaznam["pocet"];
}
else
{
$celkem=$_GET["celkem"];
}
if ($celkem>ROWS)
{
if (!isset($_GET["od"])) $od=1; else $od=$_GET["od"];
$vysledek=mysql_query("select * from psc"." limit ".($od-1).", ".ROWS);
echo "Záznamů:
".$od."-";
echo (($od+ROWS-1)<=$celkem)?($od+ROWS-1):$celkem;
echo " z celkem
$celkem ";
//začátek
- vytvoř odkaz pouze pokud nejsme na začátku
if
($od==1) echo "Začátek | ";
else echo "<a href=\"".$_SERVER["PHP_SELF"]."?celkem=$celkem&od=1\">Začátek</a> | ";
//zpět
- vytvoř odkaz pouze pokud nejsme v prvních ROWS
if
($od<ROWS) echo "Předchozí | ";
else echo "<a href=\"".$_SERVER["PHP_SELF"]."?celkem=$celkem&od=".($od-ROWS)."\">Předchozí</a> | ";
//další - vytvoř,
pouze pokud nejsme v posledních ROWS
if
($od+ROWS>$celkem) echo "Následující | ";
else echo "<a href=\"".$_SERVER["PHP_SELF"]."?celkem=$celkem&od=".($od+ROWS)."\">Následující</a> | ";
//poslední - to je
posledních (zbytek po dělení ROWS) záznamů
if
($od>$celkem-ROWS) echo "Konec <BR>";
else echo "<a href=\"".$_SERVER["PHP_SELF"]."?celkem=$celkem&od=".($celkem-$celkem%ROWS+1)."\">Konec</a><BR>";
}
?>
Ukázat
celý
skript | Spustit
skript
Všimněte si rozšíření LIMIT příkazu SELECT. Umožňuje nám vrátit
řádky "počínaje nějakým" a jen "určitý počet". Celý skript funguje
následovně:
- Jestliže je zavolán poprvé, zobrazí se prvních ROWS záznamů a
vytvoří se odkazy na stránkování
- Jestliže klikneme na odkaz "začátek", "předchozí", "následující"
nebo "konec", zavolá se skript s parametry.
- Počet řádků si zjistíme pouze poprvé a pak jej předáme jako
parametr $_GET["celkem"]
- Stránkovací odkazy jsou inteligentní. To například znamená, že
jsme-li na začátku sady, výraz "Začátek" není odkaz.
- A také se může stát, že celkový počet záznamů je menší než
maximální, a pak stránkovací povely vůbec nezobrazujeme
Zbytek skriptu je pouhá matematika; zmíním se jen o tom, že příkaz
"Konec" nezobrazí posledních ROWS záznamů, ale jen zbytek. Například
máme-li celkem 230 záznamů a krok 100, nezobrazí se nakonec záznamy
131-230, ale 201 až 230.
Chování stránkování si můžete upravit, běžně se místo
textu používají grafické symboly a počet záznamů na stránce je
nastavovací. Je rovněž možné posílat parametry pomocí metody POST, nebo
je možné skript upravit a použít jako include soubor na více místech.
Pozn.: Samozřejmě, že úplně
nejlepší je rozsáhlé sady záznamů ve skriptech nemít. Někdy se tomu ale
nevyhnete.
Prezentace dat pomocí tabulek
Zatím jsme při vypisování dat do prohlížeče používali jen echo a
<BR>. To asi v reálné aplikaci stačit nebude. Poměrně časté je
vypisovat sady záznamů do tabulek. Není to vůbec složité a
vlastně to již umíme
<TABLE>
<?
// zde je include souboru s
konstantami
mysql_connect(SQL_HOST, SQL_USERNAME, SQL_PASSWORD);
mysql_select_db(SQL_DBNAME);
$vysledek=mysql_query("select * from psc where
left(obec,2)='Be'");
while ($zaznam=MySQL_Fetch_Array($vysledek)):
?>
<TR>
<TD><?echo $zaznam["obec"]?></TD>
<TD><?echo $zaznam["psc"]?></TD>
</TR>
<?
endwhile;
?>
</TABLE>
protože kód PHP se s HTML může proplétat. Kvalitní materiál pro
studium tvorby tabulek máme na našem serveru díky seriálu
Pavla Káchy, takže se tam můžete podívat.
Často se dělá to, že se sudé a liché řádky v databázi odliší jinou
barvou pozadí. Což není problém - můžeme si například zavést logickou
proměnnou a přepínat její hodnotu mezi TRUE a FALSE a podle toho pak
řádek obarvovat:
<?
while ($zaznam=MySQL_Fetch_Array($vysledek)):
?>
<TR <?if ($sudy) echo "bgcolor=silver"?>>
<TD><?echo $zaznam["obec"]?></TD>
<TD><?echo $zaznam["psc"]?></TD>
</TR>
<?
$sudy=!$sudy;
endwhile;
?>
Ukázat
celý
skript | Spustit
skript
To má ale jednu zásadní nevýhodu - každý druhý tag <TR> má
atribut bgcolor, což neúměrně nafukuje zdrojový kód. Nezapomeňme, že
zdrojový kód se musí do prohlížeče natáhnout chtěnechtě celý. Asi
nejefektivnější řešení by bylo použít kaskádové styly. O tom se zase na
Linuxsoftu dočtete zde.
Princip prolínání kódu by byl stejný.
V dalším díle seriálu si řekneme něco o tom, jak v databázi MySQL s
daty pomocí PHP manipulovat. To znamená nejen je číst, ale i zapisovat.