Základní kurz 15: Komunikace mezi PHP a JavaScriptem

Autor: Joker
V poslední kapitole základního kurzu se podíváme na častý problém začátečníků, komunikaci mezi PHP a JavaScriptem, resp. obecně mezi PHP a technologiemi na straně klienta.

Poznámka: Tato kapitola předpokládá, že čtenář má základní znalosti JavaScriptu. Zároveň není tak klíčová pro zvládnutí samotného PHP, pokud nechcete předávat data do/z JavaScriptu, jako předchozí kapitoly.

Ilustrace problému:

(přeskočíme zbytek kódu stránky)
<script type="text/javascript">
    var odpoved = prompt("Zadej svoje jméno", "");
</script>
<?php
    // Jak se tady dostat k proměnné odpoved?

A samozřejmě i opačný problém: Jak se v JavaScriptu dostat k proměnné z PHP?

Odpověď zní: Nijak, nejde to. Připomeňme si obrázek ze samotného úvodu základního kurzu:

Z něj je zřejmé, že PHP běží jinde a jindy, než JavaScript. V době zpracování PHP se stránka ještě ani neodeslala do prohlížeče, v době zpracování JavaScriptu zase už PHP skončilo a prohlížeč ani neví, že na stránce nějaký PHP kód byl.

PHP a JS jsou tedy úplně jiné světy, nemohou sdílet proměnné a funkce. To ale neznamená, že by nešlo si mezi nimi předávat data.

Předání dat ze serveru do JavaScriptu

Vložení do stránky

Data ze serveru na klienta svým způsobem předáváme od samého začátku, například i echo "Ahoj"; je de facto odeslání dat ze serveru na klienta. Úplně stejně si do stránky můžeme vložit například prvek <input> typu hidden, jeho hodnotu (atribut value) vygenerovat v PHP a následně ji JavaScriptem přečíst.

Pokud ale hodnotu potřebujeme jen pro JavaScript, existuje ještě snazší způsob: JavaScript je součástí HTML kódu stránky a kód stránky generuje PHP, takže nám nic nebrání si v PHP do stránky vygenerovat přímo JavaScriptový kód.

Například bychom chtěli v JavaScriptu znát návštěvníkovu IP adresu. Ta je v PHP v $_SERVER["REMOTE_ADDR"] (poznámka: Nemusí to vždy být IP adresa konkrétního návštěvníkova počítače, může to být třeba adresa routeru u poskytovatele připojení, pokud návštěvník nemá veřejnou IP). Po vypsání musí vzniknout platný JavaScriptový kód, takže hodnoty musíme ošetřit na případné konfliktní znaky. K tomu se lze s výhodou použít funkci json_encode. Tato funkce převede data (předaná v parametru) do formátu JSON (JavaScript Object Notation). Protože JSON formát odpovídá syntaxi JavaScriptu (a lze ho používat přímo v JavaScriptovém kódu bez nutnosti nějaké konverze), je to vhodný formát pro výměnu dat s JavaScriptem.

Výsledek:

<script type="text/javascript">
    var ip = <?php echo  json_encode($_SERVER["REMOTE_ADDR"]); ?>;
    // teď už můžeme v JS pracovat s proměnnou ip
</script>

Po zpracování PHP dostaneme kód (IP adresa se může lišit):
<script type="text/javascript">
    var ip = "127.0.0.1";
    // teď už můžeme v JS pracovat s proměnnou ip
</script>

Je asi zřejmé, že takto můžete v PHP sestavit a do stránky vypsat libovolný JavaScriptový kód. Sestavování kódu v PHP řetězci ale není moc přehledné a vyžaduje schopnost si představit zpracovaný výstup a správně escapovat příslušné znaky. Například když budeme používat řetězce v uvozovkách a v JS budeme chtít zobrazit alert a v něm uvozovku (pro lepší čitelnost kódu s mezerami okolo), musíme escapovat (podobně jako v PHP): alert(" \" ");. A když takový kód chceme vypsat v PHP, musíme escapovat ještě i pro PHP: echo "alert(\" \\\" \");". Většinou je ale přehlednější nevkládat delší kódy přes PHP, mít je samostatně a z PHP do nich jen vkládat hodnoty.

Cookies

Data ze serveru na klienta můžeme předat i pomocí cookies. K tomu slouží v PHP funkce setcookie. Tato funkce má jeden povinný parametr (název cookie) a spoustu nepovinných, ze kterých typicky budeme potřebovat jen dva: Hodnotu cookie a expiraci. Expirace je časové razítko (timestamp) a typicky asi budete chtít použít aktuální timestamp time() plus nějakou dobu (v sekundách, takže pro dobu např. ve dnech ještě vynásobit * 3600 * 24. Možná přehlednější způsob je použít funkci strtotime, například pro cookie na 30 dní: strtotime("+30 days"); Výchozí hodnota expirace je 0, cookie se pak smaže při zavření okna prohlížeče.

Háček je, že cookies nemůžete nastavovat kdykoliv. Cookies se návštěvníkovi odesílají v hlavičce odpovědi na HTTP požadavek a hlavičky lze odesílat jen pokud ještě nebyl odeslaný žádný obsah stránky. Před manipulací s cookies tedy nesmí být žádný příkaz echo, ani nic jiného, co odešle nějaký obsah do prohlížeče (dokonce ani třeba prázdný řádek před otevírací značkou PHP, ani identifikační bajty UTF-8 kódování- právě proto je u nastavení editoru doporučeno je do souborů nevkládat).

Další háček je, že cookies jsou uložené v prohlížeči návštěvníka. Návštěvníkův prohlížeč nemusí cookies vůbec podporovat (nebo je může mít vypnuté), návštěvník může cookies mazat, nebo dokonce upravovat. Na cookies jako úložiště se tedy nelze spoléhat a hodnoty je před použitím nutné kontrolovat, stejně jako jakákoliv jiná data přijatá od návštěvníka.

S uložením v prohlížeči souvisí i to, že cookie nastavovaná na serveru bude skutečně nastavená až na příští načítané stránce (v rámci domény, pro kterou ke cookie platná). Cookie se musí nejdříve odeslat do návštěvníkova prohlížeče, tam se teprve uloží (pokud je to v prohlížeči podporováno a povoleno) a teprve s požadavkem na další stránku se odešle na server.

Předání dat z JavaScriptu na server

Formuláře

Základním způsobem předání dat na server jsou formuláře, o kterých jsme už mluvili. JavaScript má přístup k formulářovým políčkům, takže může jejich hodnoty nastavovat a kontrolovat, případně může ukládat informace do skrytých polí (<input type="hidden">). Připomeňme, že i skryté pole vyplňované JavaScriptem, nebo třeba pole vyplněné uživatelem a zkontrolované JavaScriptem, jsou na serveru pořád hodnoty přijaté od návštěvníka, takže je nutné je na serveru ještě ověřit.

Cookies

Podobně jako v PHP, i v JS je možné nastavovat a měnit cookies. Základní princip je stejný s tím, co jsme si o cookies řekli už výše, jen při nastavování cookies v JS (tedy na klientovi) odpadají problémy s přenášením v hlavičkách. Na serveru se nové hodnoty cookies opět projeví od příštího požadavku na příslušnou doménu.

Vytvoření nového požadavku na server

Kromě odeslání dat skrze formulář je možné JavaScriptem vytvářet i nové požadavky na server. V té nejjednodušší podobě to je mnohem primitivnější, než by se mohlo na první pohled zdát:

Přes obrázek

Stačí vzít nějaký prvek s obsahem načítaným z URL, obvykle se používá obrázek, jeho zdroj nasměrovat na adresu skriptu a data předat v adrese jako GET parametry.
Když vytvoříte třeba element <img src="skript.php?a=1">, když se ho prohlížeč pokusí načíst, spustí na serveru skript skript.php a bude mu předáno $_GET["a"] = 1. Skript pak může vracet nějaký obrázek, který lze dokonce podle určitých podmínek měnit a tím do jisté míry zobrazit v prohlížeči výsledek skriptu.

Obrázek lze v JavaScriptu vytvořit i takto:

var img = new Image();
img.src = "skript.php?a=1";

Podobným způsobem fungují třeba některá počítadla návštěvnosti webů (v základní podobě do měřené stránky vložíte určitý obrázek, za kterým se ale schovává skript, který započítá návštěvu. V pokročilejší variantě adresu obrázku sestaví JavaScript a zakomponuje do ní i další sledované údaje, které by jinak serverový skript jen analýzou požadavku nedokázal zjistit).

JSONP

Technika JSONP (znamená JSON with padding) se velmi podobá výše zmíněnému použití obrázku, ale místo obrázku se používá prvek <script>. Vytvoří se (nebo použije již připravený existující) prvek <script>, jehož atribut src směřuje na adresu serverového skriptu. Opět je možné skriptu předat data přes GET parametry v adrese. Zároveň je ale možná i komunikace druhým směrem, tj. serverový skript může předat data zpátky JavaScriptu.

K tomu je potřeba v JavaScriptu stránky používající JSONP mít definovanou funkci pro zpracování dat přijatých ze serveru. Řekněme, že její definice (v JavaScriptu stránky) bude třeba function processResponse(data) {…}.

Serverový skript provede svou činnost, výsledná data převede do formátu JSON zmíněného výše a obalí to voláním funkce pro zpracování dat (v našem případě něco jako: echo "processResponse(" . json_encode($data) . ");"). K převedení dat do formátu JSON opět použijeme funkci json_encode. Všimněte si, že v tomto případě nevrací PHP skript HTML kód, ale pouze jedno volání JavaScriptové funkce. Jeho výstup totiž bude na klientovi obsahem prvku <script>.

Konečný výstup ze skriptu by mohl vypadat třeba:

processResponse({"Name": "Uzivatel", "Id": 1234});

Načtení takového skriptu vyvolá metodu processResponse (která už na stránce byla od začátku) a předá jí data získaná od serverového skriptu.

Poznámka: Toto je jen rychlý popis fungování uvedené techniky. Pokud se v problematice neorientujete, před použitím této techniky v praxi by bylo dobré si nastudovat další materiály k tématu. Zejména pamatujte, že se v prohlížeči spouští nějaký předem neznámý JavaScript stažený ze serveru, což může potenciálně být bezpečnostní riziko.

Více informací o JSONP.

AJAX

znamená Asynchronous JavaScript And XML, tedy „Asynchronní JavaScript a XML“. Zatímco výše zmíněné metody k odeslání požadavku na server využívají „vedlejší účinky“ zpracování některých HTML značek, zde JavaScript už skutečně sestavuje požadavek na stránku. Používá se k tomu JavaScriptový objekt XmlHttpRequest.

Zkratka AJAX (X = XML) předpokládá, že data se budou přenášet ve formátu XML, ale ve skutečnosti se používají i jiné formáty (např. výše zmíněný JSON, nebo pokud se výstup ze serveru použije jako obsah nějakého HTML prvku, může server vracet jednoduše příslušný HTML kód, resp. část HTML kódu) a pořád se tomu říká AJAX.

Bližší informace o AJAX a jeho použití najdete v JavaScriptových učebnicích (tato učebnice se věnuje PHP a AJAX je záležitost převážně JavaScriptu).

Více informací o AJAX.

Máte návrh na vylepšení či doplnění článku? Obsahuje článek nepřesné informace, nebo v něm chybí něco důležitého?
Tento článek má diskusní vlákno na diskusi Jak Psát Web, kam můžete náměty a připomínky napsat.


Správcem webu Péhápko.cz je Joker, mail zavináč it-joker tečka cz. Informace o autorských právech a možnostech použití obsahu viz Autorská práva
Přihlášení