Předání akce a objektu
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?
akce.php?objekt=objekt
(tradiční řešení)?akce=akce&objekt=objekt
(řídící skript)?akce=objekt
(řídící skript úsporněji)
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.
Diskuse
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

Jakub Vrána
:
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í.


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

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


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.
Jakub Vrána
:
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?
Jakub Vrána
:
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.


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...

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í.

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 ;)

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, ...
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.
Jakub Vrána
:
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 styleindex.php?action=...¶m=...
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
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);
?>
Diskuse je zrušena z důvodu spamu.

