Předání akce a objektu

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

Pro vzájemné propojení souborů doporučuji vyhnout se jednomu centrálnímu skriptu a raději pro každou akci vytvořit vlastní skript. Co když ale aplikace řídící skript vyžaduje (třeba proto, že to má ve svém zadání), jak potom bude vypadat URL?

Třetí způsob neumožňuje provádět kód jako include basename($_GET["akce"]) . ".inc.php", zase ale vytváří elegantnější URL. Při využití mod_rewrite se všechny tři způsoby mohou samozřejmě tvářit třeba jako akce/objekt, tento modul ale není vždy k dispozici.

Jakub Vrána, Dobře míněné rady, 6.7.2007, diskuse: 23 (nové: 0)

Diskuse

ikona Techi:

>tvářit třeba jako akce/objekt, tento modul ale není vždy k dispozici.

Proč? :D

Tenhle tip bych ocenil někdy před lety. Dneska se snad už takhle nepíše. Akce a controller by měly být součástí URL

ikona Jakub Vrána OpenID:

Vezměme si projekt, který má běžet všude, musí mít triviální konfiguraci (nejlépe žádnou) a musí být snadno instalovatelný (nejlépe zkopírováním jediného souboru). Pro takové projekty se tento postup hodí.

ikona GEe:

Takto jednoduchý skript se dá napadnout mnoha útoky, takže mě překvapuje, že u Vás se něco takového najde.

ikona Jakub Vrána OpenID:

Sice přesně nepopisujete, o jakém skriptu mluvíte, ale mohl byste ty útoky popsat?

ikona D1ce:

Tip: $_SERVER['QUERY_STRING'] ve většině případů obsahuje řetězec za otazníkem. Dále lze projít $_GET pole foreach($_GET as $klic => $hodnota){}, ale nebude tam proměnná GLOBALS a nějak divně to croupe chaos v [] - více viz manuál. ;)

kozotoč:

<?php include basename($_GET["akce"]) . ".inc.php"; ?>

opravte mě jestli se mýlím, ale když někdo podvrhne parametr akce, který se neshoduje s žádným jménem souboru, tak to skončí výpisem chybové hlášky do stránky.

ikona Jakub Vrána OpenID:

Chybu to samozřejmě způsobí. Jestli se vypíše do stránky, určí direktiva display_errors. Ve skutečném kódu by to nejspíš bylo obalené nějakým <?php if (file_exists()) ?>.

kozotoč:

... to se může stát i když to tam do URL někdo napíše ručně a zmýlí se ve velikosti písmen. To asi není moc košér, takhle lehce připustit, že můžu na stránce vidět chybu PHP?

ikona Jakub Vrána OpenID:

Zobrazování chyb je lepší vypnout v konfiguraci a některými druhy chyb se nezatěžovat. Co asi způsobí kód <?php htmlspecialchars($_GET["query"]) ?>, když v URL přijde query[]=? Chybu, kterou podle mě nestojí za to ošetřovat.

ikona JiFF:

Přesně tak... protože IsSetit jenom kvůli ošetření prázdného indexu - kdysi jsem tomu podlehl a ošetřoval jsem to - ale je to cesta do pekel...

ikona mj41:

No jak u čeho. Psal jsem nedávno modul pro registrace předmětů a bez E_NOTICE bych se zbláznil. Prostě spoustu věcí mám v polích a každý překlep nebo neošetřený stav pěkně bolí.

ikona dgx:

Ano, E_NOTICE jsou ty nejdůležitější chyby v PHP. Během vývoje je měním na Exception a nechávám shodit aplikaci. V ostrém provozu je loguju a pečlivě analyzuju. Potlačování chyb E_NOTICE nebo E_WARNING je projevem amaterismu. Howgh ;)

ikona JiFF:

Potlačování - samo až na ostrém serveru, vypnout si to při ladění; na to bych musel mít opravdu speciální náladu =) Ale co např. prázdný index? (myslím tím právě  <?php $x = $_GET["index"]; ?> ), ošetřujete to někdo? (pokud se nepletu, generuje to jen neškodnou NOTICE, která by ale eventuelně škodila na ostrém serveru.

Ondrej Ivanic:

Ja ano, asi takto to zvyknem robit:

$id = Request::getInt('id');
$options = Request::getArray('options');

Request bola staticka trieda so zopar metodami a wrapovala pristup k _GET, _POST, _REQUEST, _COOKIES, _SESSION. Metody getxxx mohli mat validaciu (::setValidator('id', new ValidateIntMinMax($min, $max)) a default hodnotu (::getInt($name [, $default = null]))

Ta trieda sa transparentne starala o vsetok bordel ohladom magic_quotes, ...

ikona JiFF:

a naprosto zbytečná =) Je-li i tak kód dobře interpretován, proč e_warning nebo e_notice (teď nevím) nepotlačit...

Honza Odvárko:

Je třeba volit kompromis, dle zkušeností zvažovat, kde je ještě dobré počítat s možnou chybou. Jistě je nutné ošetřovat takové stavy, v nichž skript není schopný dokončit akci správně.
Záleží taky na tom, o jakou část aplikace jde. Pokud je web složen z aplikačního jádra a "modulů", pak se mi osvědčilo zachycovat jádrem veškeré chyby, varování, notices, a potom s nimi dobře naložit (logovat, poslat mailem, ...). Zkrátka použít vlastní error handler - výborná věc. Moduly a jakékoli narychlo psané doplňky už můžou počítat s jakýmsi ideálním stavem a neošetřovat každou prkotinu, protože jádro vše zachytí.

Honza Odvárko:

Co se týče velikosti písmen při includování "akčního" skriptu, lze jednoduše název akce převést fcí strtolower() a skripty pojmenovávat malými písmeny. V tom nevidím nic prasáckého.

ikona Jakub Vrána OpenID:

Lepší je v takovém případě přesměrovat na správné URL, protože vyhledávače a prohlížeče různou velikost písmen v URL považují za různé URL. Nicméně já bych takový případ asi neošetřoval vůbec a zobrazil standardní chybovou stránku.

Ondrej Ivanic:

Mama radsej jeden centralny skript v style
index.php?action=...&param=...

Kde som najprv zacinal s includovanim suboru ($action.".php") zo spravneho adresaru, potom sa action zmenilo na class.method pripadne /class/method s mod_revrite a potom to uz bol len krok k MVC.

Za ten cas co som pouzival toto riesenie som prisiel na nasledovne vyhody:
- lahsia reorganizacia adresarovej struktury aplikacie, ci uz URL, alebo adresarov
- nuti rozmyslat nad mudularnostou aplikacie. Lepsie je mat viac centralnych skritov ako jeden (aplikacia, admin rozhranie, prepojenie na externe zdroje (XML RPC), ...)

Nevyhody:
- treba vediet zopar veci o bezpecnosti a nie len tak bezhlavo includovat (realpath(), open basedir,  ...)
- pokial centralny skript robi aj ine veci ako je forward requestov treba vacsiu koordinaciu developerov

ikona mj41:

Ja to mam taky takhle raději. Ten hlavní skript připravuje vše pro ostatní skripty (moduly), které většinou spouštím přes output buffer. Když modul vrátí chybu tak jen vypíšu pole error_msgs. Vyjímky nepoužívám.

Jednotlivými skripty se dá udělat něco podobného. Ale hrozně nerad duplikuji kód a i to require a volání stejných funkcí na začátku a na konci by mi vadilo.

Honza Odvárko:

> Třetí způsob neumožňuje provádět kód jako include basename($_GET["akce"]) . ".inc.php"

Umožňuje (vím že to víš):
list($akce,$objekt) = each($_GET);

Ovšem jen za předpokladu, že bude dvojice akce=objekt vždy na prvním místě dotazu.

krteczek:

Začal jsem používat čtvrtý způsob, adresa vypadá:
cokoliv.php?nazevScriptu
prostě první parametr v adrese je vždycky název stránky kterou volám, správnost validuji podle arraye, kde klíče jsou názvy které očekávám z get a hodnoty jsou názvy funkcí, cesty ke scriptum, ... z te array taky generuji samotné menu. ale je to vhodné pro malé věci nebo (hlavně) pro administrační rozhraní.

Megaloman:

Já naopak doporučuji se vyhnout NEcentrálnímu řídícímu skriptu... samozřejmě jen, když člověk ví, co dělá, jinak napáchá více škody, než užitku.

A co třeba přístup, který se bude líbit MVC routeru:
index.php?model=produkt&view=html&controller=zobrazit&default_parameter=zahradni_zidle

S dobře nastavenými mod_rewrite rules pak budou odkazy vypadat například takto:

www.example.com/produkt/zobrazit/zahradni_zidle.html

Ve skriptu pak je
<?php

require $controller . '.php';
require
$model . '.php';
require
$view . '.php';

?>

nebo

<?php

$model
= new $model();
$view = new $view();
$controller = new $view($default_parameter, $model, $view);

?>

Vložit komentář

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:

avatar © 2005-2018 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.