Interval.cz
Superglobßlnφ prom∞nnΘ v PHP

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" />
  <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₧kav²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."\";");
}


Jan Dudek (26.4. 2003)

Redakce Interval.cz |  Inzerce na Interval.cz |  Hledßme novΘ autory ISSN 1212-8651 
 ⌐ Zoner software, s.r.o., vÜechna prßva vyhrazena, tento server dodr₧uje prßvnφ p°edpisy o ochran∞ osobnφch ·daj∙.