Tento článek je určen pro začínající programátory PHP. K jeho napsání mě přivedly neustále se opakující dotazy na různých programátorských fórech a diskusích. Oním problémem je získávání hodnot předaných v adrese stránky nebo obdržených z formuláře. Nebo jinak, tenhle článek snad již konečně odpoví na věčnou otázku: „Proč mi ten příklad z knihy nefunguje?“

Ze své zkušenosti vím, že problematika předávání hodnot proměnných je mnohým (hlavně) začátečníkům v PHP stále nejasná. Částečně za to mohou starší, ale oblíbené knihy o PHP, které superglobální pole vůbec nezmiňují, ale často také lenost programátorům vlastní.

Trocha historie předávání proměnných

V každé starší učebnici jazyka PHP asi najdete hned na začátku podobný příklad. Jde o známou ukázku adresy s předanými daty, například http://www.nejaky_server.cz?var=10 i s vysvětlením, že PHP automaticky zaregistruje proměnnou $var a přiřadí jí hodnotu 10. A jsme u skutečného kamene úrazu. Tento postup, kdy se předávaná proměnná rovnou zaregistruje, není příliš bezpečný, protože relativně snadno může dojít k podvrhům a nabourání celého skriptu.

Problém nastane, pokud náš programátor bude chtít tento postup vyzkoušet. To, zda se bude proměnná automaticky registrovat, ovlivňuje nastavení PHP v konfiguračním souboru php.ini, konkrétně direktiva register-globals. Od PHP 4.2 je tato direktiva nastavena na Off, automatická registrace proměnných je tedy vypnuta. A to je přesně ten důvod, proč spousta nováčků dostává z PHP bolení hlavy.

Superglobální proměnné

Zatím jsme si pouze řekli, proč příklady z knih přestaly fungovat. To ovšem programátora uspokojí jen stěží. Jak tedy lze tyto hodnoty získat? Odpověď je prostá – pomocí superglobálních proměnných.

Definice superglobálních proměnných je vcelku prostá. Jde o předdefinovaná pole, obsahující hodnoty proměnných, získané ze serveru nebo od uživatele. Tato pole jsou automaticky globální, tedy automaticky „viditelná“ odevšad. Proto se jim také říká automatické proměnné. Zaměřme se nyní na jednotlivé superglobální proměnné…

Hodnoty získané z URL

Pro ukázku si představme fiktivní adresu http://www.nejaky_server.cz?var=10&mode=A. Hodnoty předávané pomocí URL se také nazývají hodnoty předané metodou GET. PHP automaticky vytvoří superglobální pole $_GET[], obsahující všechny předané hodnoty. Jednotlivé indexy jsou tvořeny přímo jménem předávané proměnné. V našem případě tedy bude pole $_GET[] obsahovat dvě hodnoty indexované pomocí jmen proměnných:

echo($_GET[„var“]); // vypíše 10
echo($_GET[„mode“]); // vypíše A

Hodnoty předané přes HTTP protokol

Hodnoty získané z formulářů se obvykle předávají pomocí HTTP protokolu metodou POST. Zcela analogicky PHP definuje superglobální pole $_POST[], s hodnotami proměnných indexované pomocí XHTML atributu name. Mějme například následující jednoduchý formulář:

<form method=“post“ action=“form.php“>
  Jméno: <input type=“text“ name=“user“ />
  <input type=“hidden“ name=“secret“ value=“1″ /&gt
  <input type=“submit“ />
</form>

Pokud tímto formulářem uživatel odešle jméno Kuba, bude výstup ve skriptu form.php vypadat následovně:

echo($_POST[„user“]); // vypíše Kuba
echo($_POST[„secret“]); // vypíše 1

Posílání souborů

Specifický je problém získávání souborů od uživatele pomocí formuláře. Nadefinujme si jeden takový:

<form method=“post“ action=“file.php“ enctype=“multipart/form-data“>
  tvoje fotka: <input type=“file“ name=“photo“ />
  <input type=“submit“ />
</form>

V tomto případě PHP není vůbec lakomé a poskytne pole hned dvojrozměrné. První index představuje atribut name, převzatý z formuláře, druhý index jednotlivé hodnoty týkající se zadaného souboru. V našem případě to bude vypadat následovně:

položka význam
$_FILES[„photo“][„name“] původní jméno souboru
$_FILES[„photo“][„size“] velikost v bytech
$_FILES[„photo“][„type“] MIME typ souboru
$_FILES[„photo“][„tmp_name“] dočasné jméno souboru, pod kterým byl uložen na serveru
$_FILES[„photo“][„error“] chybový kód

Další předávané hodnoty

Zcela obdobně PHP automaticky vytváří pole $_COOKIES[] a $_SESSIONS[], která obsahují hodnoty získané z cookies a relací (sessions). A čistě pro úplnost se hodí zmínit superglobální pole $_SERVER[] a $_ENV[], obsahující hodnoty předané samotným serverem a prostředím, odkud byl skript spuštěn.

Všechny hodnoty zadané uživatelem

Pokud je nám jedno, z jakého zdroje jsou proměnné předávány, můžeme použít automatické pole $_REQUEST[], obsahující všechny předané hodnoty. Osobně toto pole příliš nedoporučuji ze dvou důvodů: Pokud používáte konkrétní pole $_GET[], $_POST[], $_FILES[]..., ihned ze zdrojového kódu poznáte nejen jméno předávané proměnné, ale i její zdroj. Tento „luxus“ mi u pole $_REQUEST[] chybí. U pole $_REQUEST[] může navíc dojít k problému, mají-li stejné jméno proměnné převzaté z různých zdrojů. Potom se zaregistruje samozřejmě pouze jedna.

O tom, v jakém pořadí k registraci do $_REQUEST[] dojde, rozhoduje direktiva variables_order. Nabývá hodnoty řetězce skládajícího se z posloupnosti písmen EGPCS (počáteční písmena slov Environment, Get, Post, Cookie, Server). Jak asi tušíte, později uvedený zdroj vždy přepíše proměnné ze zdroje uvedeného dříve, pokud mají stejné jméno. Například zmíněný řetězec EGPCS nejdříve zaregistruje proměnné z prostředí, pak proměnné převzaté z adresy, z HTTP protokolu, z cookies a nakonec ze serveru. Pokud některé písmeno vynecháte, nebudou dané proměnné zaregistrovány vůbec, a to ani do „svých“ automatických polí $_*[]! Standardně je direktiva variables_order nastavena na GPCS.

Jen tak na okraj

Mimo již probraných polí $_*[] v PHP existují starší pole $HTTP_GET_VARS, $HTTP_POST_VARS, $HTTP_COOKIE_VARS, $HTTP_POST_FILES, $HTTP_ENV_VARS. Tato pole jsou ale označena za deprecated (překonaná) a neměli byste je používat. Navíc nejsou superglobální, což velmi zjednodušeně znamená, že v každé funkci musíte na začátku uvést například global $HTTP_GET_VARS, abyste je mohli v jejím těle používat.

Špetka nostalgie

Pokud by vám automaticky registrované proměnné přece jenom z nostalgie chyběly, nebo se vám stále nechtělo psát celý název pole, mám zde pro vás jednoduchý skript, který zaregistruje všechny položky automatického pole $_REQUEST[] jako samostatné proměnné. Tento skript je také dobře použitelný, pokud chcete své starší skripty spouštět na novější verzi PHP se zakázanou automatickou registrací a nechce se vám ve zdrojovém kódu přepisovat všechna jména předávaných proměnných.

foreach($_REQUEST as $ind => $val)
{
  $val=addslashes($val);
  eval(„$“.$ind.“=\““.$val.“\“;“);
}

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

3 Příspěvků v diskuzi

  1. foreach($_REQUEST as $ind => $val)
    {
    $val=addslashes($val);
    eval(„$“.$ind.“=\““.$val.“\“;“);
    }

    Je to nefunkční..

  2. eval zahodit, existuji i promene jmene definovane podle obsahu jine promene (dynamicky jmenovane). pak plati:
    foreach($_REQUEST as $ind => $val)
    {
    $ind=addslashes($ind);$val=addslashes($val);
    $$ind=$val;
    }

Odpovědět