PHP

nejen dynamicky generované stránky

Jirka Kosek <jkj@ucw.cz>

Abstrakt

PHP je freewarový systémem vhodný pro dynamické generovaní webových stránek. Cílem přednášky je seznámit posluchače se základními možnostmi systému -- zejména se zpracováním formulářů a s možnostmi propojení s různými databázovými servery. Stranou nezůstane ani porovnání PHP s ostatními technologiemi jako je CGI a ASP. V duchu celého semináře bude i stručná úvaha nad intranetovým informačním systémem, který může být zcela vystaven pouze na free technologiích jako je Linux, PHP a TeX a přitom funkčností zdaleka předčít mnohé komerční systémy.

Konec statických stránek

První implementace služby World-Wide Web počítaly s tím, že informace prezentované pomocí HTML stránek nebudou příliš proměnlivé v čase, a proto byly HTML stránky uloženy v souborech. V případě potřeby mohl autor stránky její text změnit v souboru a od té doby byla přístupná nová podoba stránky.

Časem se přišlo na to, že koncept služby WWW je natolik obecný, že není problém pomocí stávajícího modelu zpřístupnit interaktivní služby jako různé vyhledávací systémy apod. Vše bylo postaveno na velice jednoduchém principu -- HTML stránky již nejsou uloženy v souboru, ale generovány nějakým programem, který umí přebírat parametry z formulářů začleněných do stránky. Protože již HTML stránky nejsou staticky umístěny v souborech, ale generovány podle potřeby, hovoříme o dynamicky generovaných stránkách.

Díky dynamicky generovaným stránkám se před Webem objevil nový svět zpřístupňování rozsáhlých databází, podnikových informačních systémů ovládaných pouze pomocí prohlížeče, virtuálních obchodních domů apod. Dá se říci, že prohlížeče se staly novou platformou pro provozování aplikací.

V poslední době sílí tlak, který nutně vyústí v to, že většina stránek dostupných na Webu bude generována dynamicky. Čím je to způsobeno? Ať chceme nebo ne, dnes již hlavní těžiště Internetu nespočívá na akademické půdě, ale v čistě komerční oblasti. Pokud chce nějaká firma pomocí své webové prezentace případné zákazníky zaujmout, musí nabízet víc, než jen jednou za půl roku aktualizované statické stránky.

Uživatel se na stránky bude vracet pouze v případě, že zde často najde něco nového. Pokud tedy při každé návštěvě bude firemní stránka doplněna jiným vtipem či zde bude možnost odpovědět na otázku v nějaké soutěži, počet návštěvníku a zejména těch opakovaně se vracejících jistě stoupne. Podobné chování Webu však nelze dosáhnout použitím statických stránek, musí se použít nějaký ze systémů pro dynamické generovaní stránek.

Jestliže tedy před rokem či dvěma bylo pro tvůrce stránek nezbytné se naučit jazyk HTML, dnes je nejvyšší čas na osvojení si některé technologie pro dynamické generování stránek. Jednou z těchto technologií je systém PHP s jehož základními rysy se nyní seznámíme.

Dobrý den, jmenuji se PHP

Historie systému PHP začíná zhruba v roce 1994, kdy Rasmus Lerdorf napsal jednoduchý systém pro evidenci přístupu ke stránkám. Tento systém se postupně vyvíjel až se z něj stal plnohodnotný skriptovací jazyk s velice bohatou knihovnou funkcí. Poslední verzí PHP je 3.0, ostrá verze je k dispozici od června 1998. Přibližně jednou za měsíc je uvolněna nová podverze, která obsahuje opravy chyb předešlých verzí a často přidává podporu pro další nové knihovny.

Práce s PHP je velice jednoduchá a intuitivní. Na místo psaní programů, které ve výsledku vygenerují HTML, používá PHP opačný přístup. Do HTML stránky můžeme zapsat příkazy PHP, jejichž výsledek se po interpretaci skombinuje s okolním HTML kódem.

Syntaxe PHP je převážně odvozena z jazyka C. Některé rysy jsou převzaty z Perlu a z Javy -- např. asociativní pole a třídy. Kromě jednoduchého a mocného jazyka, je velikou devizou PHP obrovské množství zabudovaných funkcí, které mimo jiné zahrnují:

Dosud nezmíněnou a přitom velice podstatnou vlastností PHP je jeho nezávislost na platformě. PHP pracuje pod operačními systémy Unix, Windows 95/98/NT a Macintosh. Existují i projekty, které se snaží o portování PHP na různé starší mainframe. Kromě nezávislosti na operačním systému je PHP nezávislé na použitém WWW-serveru. PHP může spolupracovat s libovolným serverem, který podporuje rozhraní CGI -- to dnes podporují snad všechny servery. Pokud používáme Apache, může být PHP spuštěno jako jeho modul, čímž dosáhneme mnohem vyššího výkonu a větší bezpečnosti. Připravovaná verze PHP 3.1 bude zahrnovat i moduly ISAPI (Microsoft), NSAPI (Netscape) a WSAPI (O'Reilly) a umožní běh PHP jako modulu na většině WWW-serverů pod Windows.

Přenositelnost skriptů napsaných v PHP je velkou výhodou. Poměrně často si dnes různé firmy a instituce pořizují server s Windows NT. Až časem zjistí, že to z hlediska stability a výkonu nebyla nejlepší volba. Pokud při vytváření dynamických stránek použijí PHP, není žádný problém na počítači nainstalovat nějaký Unix podporující platformu Intel (Linux, FreeBSD, Solaris) a stránky napsané v PHP provozovat vesele dál.

Lehký úvod do PHP

Vytváření jednoduchých skriptů v PHP se příliš neliší od tvorby běžných webových stránek. Pouze stránky ukládáme do souborů s příponou php nebo php3, aby se odlišily od stránek, které neobsahují příkazy pro PHP. Příkazy PHP zapisujeme mezi znaky '<?' a '?>'.

S využitím funkce Date() není problém na všech stránkách zobrazovat například aktuální čas:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Ukázka použití funkce Date</TITLE>
</HEAD>
<BODY>
<DIV ALIGN=CENTER>
<H1>Vítejte na našem serveru</H1>
<P>Právě je <?echo Date("H:i:s")?>
</DIV>
</BODY>
</HTML>

V ukázce jsme použili příkaz echo, který slouží k vypisování hodnot. V naše případě vypisujeme hodnotu vrácenou funkcí Date(). Tato funkce vrací informace o aktuálním datu a čase zformátované podle zadané specifikace formátu.

Výsledek použití funkce Date()
Výsledek použití funkce Date()

Formuláře jsou vstupní branou do interaktivního světa Webu. Pomocí formulářů mohou uživatelé na stránkách zadávat objednávky, klást dotazy na různé databáze apod. Aby však nebyl formulář jen černou dírou, musí k němu existovat skript, který uživatelem zadaná data zpracuje a na jejich základě poskytne uživateli adekvátní odezvu.

My si snadnost práce s parametry z formuláře ukážeme na jednoduché aplikaci. Uživatel do formuláře zadá své jméno a svůj věk. Skript pak vysloví nemilosrdný soud nad jeho věkem. Nejprve vytvoříme stránku s formulářem:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Jednoduchý formulář</TITLE>
</HEAD>
<BODY>
<P>Vyplňte následující údaje
<PRE>
<FORM ACTION="obsluha.php" METHOD=POST>
Jméno: <INPUT NAME=Jmeno>
Věk:   <INPUT NAME=Vek>
<INPUT TYPE=Submit VALUE="Odeslání formuláře">
</FORM>
</PRE>
</BODY>
</HTML>

Stránka s formulářem
Stránka s formulářem

Takto vytvořený formulář vyvolá po odeslání skript obsluha.php. Tomuto skriptu je předán obsah všech polí formuláře. PHP automaticky pro všechna pole formuláře vyrobí proměnné s odpovídajícím názvem. Ve skriptu proto můžeme používat proměnné $Jmeno a $Vek, které obsahují text zadaný uživatelem do polí pro jméno a věk. Není tedy problém napsat skript, který generuje různé výstupy právě podle obsahu formulářových polí.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Obsluha formuláře</TITLE>
</HEAD>
<BODY>
<H1>Výsledek obsluhy formuláře</H1>
<?  
    echo $Jmeno." je ";
    if ($Vek < 10):
        echo "pěknej mlíčnák";
    elseif ($Vek < 20):
        echo "teenager";
    elseif ($Vek < 60):
        echo "v nejlepších letech";
    elseif ($Vek < 100):
        echo "pravděpodobně prarodič";
    else:
        echo "někde mezi stovkou a smrtí";
    endif
?>.
</BODY>
</HTML>

Výsledek obsluhy formuláře
Výsledek obsluhy formuláře

Opravdovou lahůdkou, kterou nám PHP nabízí, je snadná spolupráce s databázemi. Skripty mohou pomocí jazyka SQL (Structured Query Language) provádět s údaji v databázích libovolné operace.

Možnosti praktického využití databází jsou opravdu velmi široké. My si ukážeme jednoduchý skript, který uživatelům umožňuje pohodlné hledávaní v adresáři firem.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>Prohledávání adresáře firem</TITLE>
</HEAD>
<BODY>
<H1>Prohledávání adresáře firem</H1>
<FORM>
Zadejte začátek názvu firmy: <INPUT NAME=Nazev VALUE="<?echo $Nazev?>">
<INPUT TYPE=Submit VALUE="Hledej">
</FORM>
<HR>
<?
if ($Nazev!=""):
    $spojeni = ODBC_Connect("test", "", "");
    if (!$spojeni):
        echo "Nepodařilo se připojit k databázi.";
    else:
        $vysledek = ODBC_Exec($spojeni, 
                    "SELECT * FROM Adresy WHERE Nazev LIKE '$Nazev%'");
        if (!$vysledek):
            echo "Chyba při provádění dotazu v databázi.";
        else: 
            echo "Počet nalezených adres: ".ODBC_Num_Rows($vysledek);
            echo "<TABLE CELLPADDING=2 CELLSPACING=0 BORDER=1>\n";
            echo "<TR BGCOLOR=SILVER><TH>Název</TH><TH>Telefon</TH></TR>\n";
            while (ODBC_Fetch_Row($vysledek)):
                echo "<TR><TD>".ODBC_Result($vysledek, "Nazev")."</TD>";
                echo "<TD>".ODBC_Result($vysledek, "Tel")."</TD></TR>\n";
            endwhile;
            echo "</TABLE>\n";
        endif;
    endif;
endif;
?>
</BODY>
</HTML>

Ukázka spolupráce s databází
Ukázka spolupráce s databází

Dovolte alespoň stručný komentář k celému skriptu. Náš příklad pro přístup k databázi používá standardní rozhraní ODBC. Je to jedna z možností, kterou PHP při přístupu k databázím nabízí. Voláním funkce ODBC_Connect() se připojíme k databázovému serveru. Funkce ODBC_Exec() slouží k zadání dotazu v jazyce SQL. Výsledek dotazu postupně zpracováváme pomocí funkcí ODBC_Fetch_Row() a ODBC_Result(). Jak jste jistě vytušili, funkce ODBC_Num_Rows() vrací počet záznamů, které vyhovují dotazu. Výsledek pak přehledně formátujeme pomocí tabulky.

PHP versus CGI

PHP samozřejmě není jediným systémem, který umožňuje dynamické generování webových stránek. Vůbec první technologií, která umožňovala automatické generování stránek, byly CGI-skripty, jejichž název je odvozen z rozhraní CGI (Common Gateway Interface). Toto rozhraní se používá pro předávání dat mezi WWW-serverem a skriptem.

Výhodou CGI-skriptů je jejich nezávislost na použitém programovacím jazyce. Stačí, když daný programovací jazyk umí pracovat se standardním vstupem a výstupem. CGI-skripty se tak nejčastěji píší v Perlu nebo příkazovém shellu případně v C/C++.

Použití CGI-skriptů je však v porovnání s PHP poměrně těžkopádné a přináší mnohem více potencionálních bezpečnostních rizik. Prvním problémem je už samotné dekódování dat získaných z HTML-formulářů. Data odesílaná prohlížečem jsou upravena tak, aby bezpečně přežila přenos pomocí protokolu HTTP. PHP data automaticky rozkóduje do jejich původní podoby. V CGI-skriptu se o převod musíme postarat sami nebo použít nějakou knihovnu, která tuto práci odvede za nás.

Další nepříjemností je poněkud těžkopádné kombinování HTML-kódu s kódem CGI-skriptu. Veškeré HTML zde musí být vygenerováno použitím příkazu print nebo jeho obdoby. To vývojáři přináší spoustu zbytečného psaní.

Asi největším problémem CGI-skriptů, zvláště pro začínající vývojáře, je umění napsat bezpečný skript, který neumožní jeho zneužití hackerem. CGI-skripty psané v příkazovém shellu nebo v Perlu lze ošálit odesláním vhodných dat. Pokud tato data obsahují speciální znaky, které například v shellu ukončují příkazy, může hacker spustit na serveru prakticky libovolný program. Správné ošetření všech pro shell nebezpečných znaků potřebuje notnou dávku zkušeností.

Poslední argumentem, který hovoří pro PHP, je výkon. Pokud PHP běží jako modul serveru, je neustále zavedeno v paměti a může velice rychle obsluhovat všechny požadavky. Pro každý požadavek, který má být obsloužen CGI-skriptem, musí být spuštěn nový proces, což není úkon zrovna nejrychlejší. CGI-skript může být rychlejší v případech, kdy provádí nějaké časově náročné operace -- zkompilované céčko je mnohem rychlejší než interpretované PHP. Nic však nebrání tomu napsat kritické rutiny v C a pomocí PHP API je zpřístupnit jako funkce pro skripty v PHP.

Na velice podobném principu jako PHP pracují i další skriptovací jazyky jako ASP (Active Server Pages) a ColdFusion. Jedná se však o komerční a nikterak levné systémy. Jejich další nevýhodou je malé spektrum podporovaných platforem. Dnes pracují pouze ve Windows a na přenosu do Unixu se teprve pracuje.

Za hranice Webu

Díky velké flexibilitě Linuxu lze s PHP provádět opravdu netušené věci. Naznačíme alespoň některé možnosti. Napsat informační systém, který bude přístupný pomocí dynamických stránek generovaných pomocí PHP, není problém. Ale co když potřebujeme něco vytisknout? Tiskový výstup současných prohlížečů jistě nelze považovat za dostačující. Nic nám ale nebrání v umístění tlačítka tisk přímo na stránku. Stiskem tohoto tlačítka můžeme vyvolat skript v PHP, který spustí TeX a předá mu požadovaný dokument k vysázení. Perfektně zformátovaný dokument pak můžeme vytisknout na síťové tiskárně, která je nejblíže uživateli, který stiskem tlačítka vyvolal tisk.

V podobných příkladech bychom mohli pokračovat do nekonečna. Proč? Protože poměr výkon/cena je u Linuxu, PHP i TeXu nekonečno resp. ${výkon\over cena} = \infty$.

Další informace o PHP