Kterak použít funkce pro bufferování výstupu při zobrazení dat na PHP portále.
8.12.2004 15:00 | Petr Zajíc | přečteno 38863×
Náš portál jsme minule zanechali ve stavu, kdy nešluo uspokojivě vyřešit zadání koncertu a přesun na stránku se seznamem koncertů kvůli problémům s hlavičkami. Naznačil jsem, že řešením bude zapnout bufferování výstupu. Pojďme to trochu rozebrat.
Normálně PHP funguje tak, že při zpracování skriptu, zjednodušeně
řečeno:
Toto chování lze změnit pomocí tzv. funkcí pro řízení výstupu. Mezi nejvýznamější patří funkce ob_start a ob_end_flush. Ob_start zapíná bufferování výstupu, ob_end_flush bufferování vypíná a odesílá nasyslený buffer prohlížeči. Pokud zavoláte funkci ob_start, je kód normálně prováděn, ale s následujícími změnami:
To má dvě výhody, obě poměrně podstatné. Jelikož mohou být jednotlivá volání funkcí print a echo celkem náročná na čas, vede obvykle bufferování výstupu ke zrychlení celé aplikace. A navíc, což je podstatné pro nás, bufferování výstupu rovněž umožní odeslat hlavičky nebo nastavit cookie proměnné i v případě, kdy už byl do bufferu odeslán nějaký výstup. Můžeme tedy směle veprostřed skriptu zavolat hlavičku s požadavkem na přesměrování na jinou stránku, a ono to bude fungovat! Nic nám tedy nebrání zabalit celý výstup do bufferování například hned úpravou souboru index.php:
<?
ob_start();
session_start();
require "./func.php"; ?>
<HTML>
... atd
</HTML>
<?ob_end_flush();?>
Pozn.: Konkrétně odeslání hlavičky
Location samozřejmě znamená, že je předchozí obsah bufferu bez použití
zahozen, protože nová stránka je někde úplně jinde, ale v našem
příkladu je to přesně to, co chceme. Uvědomme si, že je sice zahozen
výstup, který by normálně dorazil do prohlížeče, ale programový kód ve
skriptu se klasicky provedl. Provedlo se tedy i vložení řádku do
databáze.
Z bufferováním výstupu se dají provádět kouzla - například lze
nastavit, aby se před výstupem bufferu provedla nějaká funkce, buffer
lze zahodit, upravit, prohlédnout, konvertovat mezi znakovými sadami a
podobně. Jeho nejdůležitější
použití však spočívá v tom, že se nemusíme úzkostlivě starat o
odesílání hlaviček. Prohlédněte si celý upravený soubor index.php.
Vyřešili jsme přesměrování na stránku se seznamem koncertů. Pojďme
tedy teď koncerty zobrazit. To je činnost, při níž se toho nenaučíme
moc nového - probíralo se to v díle o zobrazení
dat z databáze. Jediný zádrhel bude spočívat v tom, že musíme nějak
elegantně vyřešit zobrazování českého data, koncerty seřadit (asi
vzestupně) a zajistit jen zobrazení těch, které jsou v budoucnu.
Řazení zajistí klauzule ORDER BY v dotazu pro databázi. Zobrazení jen koncertů, které nastanou v budoucnosti zajistí rovněž dotaz, protože jazyk MySQL zná funkce pro manipulaci s daty, které umí vrátit aktuální datum. Musíme však dát pozor na jednu věc - MySQL funkce NOW() vrací nejen datum, ale rovněž čas. To je pro naše účely poměrně nešikovné, protože ve sloupci datum máme uložen pouze údaj o datumové části dne, nikoli čas. Rovněž musíme dát pozor na to, že koncert konající se dnes by měl být na webu také zobrazen. Správný dotaz tedy bude využívat jinou funkci, a sice curdate():
select * from koncerty
where datum >= curdate() order by datum
Při zobrazování česky formátovaného datumu máme na výběr z několika možností. Jeden způsob je využít formátovacích funkcí mysql, konkrétně funkce DATE_FORMAT. Tahle funkce se ale několikrát měnila, takže nikdo z hlavy neví, jak bude na té které verzi databáze fungovat. Proto využijeme druhou možnost, a to je zformátování data přímo pomocí PHP funkce date, resp. strftime. Rozdíl mezi nimi je ten, že strftime bere ohledy na národní prostředí. Se zobrazováním datumů je vůbec legrace, protože MySQL nám nevrátí číslo, ale řetězec. Z řetězce tedy nejprve musíme vyvěštit datum a to následně převést. Já používám následující funkci:
function
ceskedatum ($datum)
{
if ($datum =="") return "";
return strftime("%d.%m.%Y",strtotime($datum));
}
Ani čas se nám asi nebude líbit zobrazený s přesností na vteřiny,
naštěstí tady je pomoc snadná. Protože délka řetězce reprezentující čas
je konstantní, stačí prostě zobrazit jen určitý počet znaků zleva a je
to.
Ještě jeden detail. Může se stát, že v databázi nebudu zadány žádné koncerty, nebo nebudou žádné koncerty v budoucnosti. Stránka by se v takovém případě zobrazila prázdná. To je formálně správně, jenomže by to mohlo uživatele mást. Nevěděl by, zda nejsou koncerty zadané, nebo zda je nějaká chyba na webu. Upravíme tedy skript tak, aby nám v takovém případě řekl, že dotaz sice proběhl, ale nevrátil žádné výsledky.
Postačí volat funkci mysql_num_rows()
bezprostředně po volání výběrového dotazu. Jen pozor - je třeba
pamatovat na to, že celá tabulka s výsledky se bude kreslit pouze v
případě, že nějaké výsledky byly vráceny. Tudíž, i její záhlaví se musí
konstruovat až v případě, kdy existuje nenulový počet výsledků, jinak
vznikne nevalidní stránka. Kód stránky zobrazkoncert teď může vypadat
nějak takto:
$vysledek=mysql_query("select * from koncerty
where datum >= curdate() order by datum",$GLOBALS["link"]);
if (mysql_num_rows($vysledek)==0)
echo "-- Není
naplánován žádný koncert --";
else
{
echo "<TABLE>";
while ($zaznam=MySQL_Fetch_Array($vysledek)):
?>
<TR>
<TD><?echo ceskedatum($zaznam["datum"])?></TD>
<TD><?echo substr($zaznam["cas"],0,strlen($zaznam["cas"])-3)?></TD>
<TD><?echo $zaznam["misto"]?></TD>
</TR>
<?
endwhile;
echo "</TABLE>";
}
Na současný stav projektu se můžete na našem webu podívat
nebo si jej můžete stáhnout.
Pozn.: Aby Vám stažená verze fungovala na lokálním stroji, upravte si hodnotu konstant SQL_HOST, SQL_USERNAME, SQL_PASSWORD a SQL_DBNAME. Případně si je můžete včlenit do konfiguračního souboru podobně, jako jsem to udělal v souboru func.php.