Odkazování na sebe sama

Školení, která pořádám

V PHP je k dispozici několik obratů, jak se soubor může odkazovat sám na sebe. Kromě „konstanty“ __FILE__, která vždy obsahuje absolutní cestu k aktuálně zpracovávanému souboru (hodí se např. tehdy, když chceme vložit soubor ve vložené knihovně: include dirname(__FILE__) . "/soubor.inc.php"), je definováno ještě několik $_SERVER proměnných. Následující platí pro Apache, u jiných serverů by to mělo být obdobně.

podmínkypožadavek / 'REQUEST_URI''PHP_SELF''SCRIPT_NAME'
DirectoryIndex index.php/?a/index.php/index.php
AcceptPathInfo/item.php/clanek-1?a/item.php/clanek-1/item.php
ErrorDocument/clanek-1?a/item.php/item.php
RewriteEngine/clanek-1?a/item.php/item.php
PHP-clitest/item.php / nenastavenotest/item.php od PHP 4.3.0test/item.php

Pro vytvoření absolutního URL na související soubor (např. pro hlavičku Location nebo pro poslání e-mailem), se často používá funkce dirname. Ta má však tu nevýhodu, že pro kořenový adresář vrací / a v jiném případě řetězec lomítkem neukončuje. Lepší je proto použít např. tento zápis:

<?php
header("Location: http://$_SERVER[SERVER_NAME]" . substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], "/")) . "/");
?>

Skripty pak bez problémů fungují jak v kořenovém adresáři webového serveru, tak v podadresáři.

Za zmínku stojí také proměnná 'SERVER_NAME'. Pokud mě paměť neklame, byla v prastarých verzích PHP nastavena na hodnotu gethostbyname($_SERVER["SERVER_ADDR"]), takže se při použití VirtualHost nedala použít a bylo nutné se spoléhat na 'HTTP_HOST'. Tato proměnná ale zase není k dispozici při použití HTTP/1.0. Nyní by proměnná 'SERVER_NAME' měla obsahovat vždy tu správnou hodnotu.

Odkazování na sebe sama se často používá u atributu <form action>. Pokud ale skriptu např. nechceme předat nějaké další parametry, stačí jako hodnotu použít prázdný řetězec. Jak píše Sean Coates, je potřeba proměnnou 'PHP_SELF' ošetřit stejně jako ostatní uživatelská data.

Jakub Vrána, Výuka, 21.12.2005, diskuse: 7 (nové: 0)

Diskuse

ikona dgx:

Možná by ještě stálo za to do tabulky vložit případ, kdy se volá skript např. "xyz/index.php?params", který není v URI uveden, tedy "xyz/?params".

Jinak používání dirinfo(__FILE__) nebo realpath(dirinfo(__FILE__)) je tak časté, že by stálo za zvážení vytvoření magické konstanty jako __DIR__ :-)

ikona Jakub Vrána OpenID:

Díky za tip, doplnil jsem to.

Místo dirinfo() máš na mysli asi dirname().

Jirka Bráza:

Použití prázdného řetězce ve form action je zrádné - jako cílové URL se totiž odešle URL aktuální, včetně GET parametrů. Pokud tedy stránka obsahující formulář obsahuje nějaké  parametry předané přes GET, a nevyplním action u formuláře, jsou tato data odeslána také. Často to nemusí znamenat nic, ale někdy to má důsledky, které se fakt těžko hledají.

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL: Reakce na: Jirka Bráza

Franta:

To bohužel nefunguje (zrovna by se mi to hodilo) – po odeslání formuláře se GET parametry (?foo=bar&xxx=yyy) ztratí a nová URL obsahuje jen ty parametry, které jsou explicitně uvedené ve formuláři.

Zbyněk:

já to mám napsané takto a vždy to funguje:
<?php
echo "<form method=\"post\" action=\"{$_SERVER["PHP_SELF"]}?{$_SERVER["QUERY_STRING"]}\">";
?>

ikona Jakub Vrána OpenID:

To je špatně z několika důvodů. Jednak to neřeší daný problém, kde se požaduje odeslání metodou GET. Dále PHP_SELF i QUERY_STRING jsou podstrčitelné, takže musí být ošetřeny funkcí htmlspecialchars().

zbyněk:

ano, máte pravdu, špatně jsem si to přečetl, takže jsem byl trochu vedle..
avatar © 2005-2019 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.