Zkratka na hlavní stranu: Alt + Shift + horní 2(ě)
Linkedin FB e-mail Google Plus Twitter

Hledat na tomto webu

 
 

Osobní blog
Soukromý, neprofesní mikroblog.
Článek č. 154

 


PHP: Efektivní testování parametru pro výchozí volbu při neodeslání formuláře v intranetové aplikaci



// Úvod – připomenutí podstatného z předchozího článku

Před časem jsem na blog napsal článek o pořadí argumentů okolo logického operátoru and:
https://www.adamek.cz/blog/?blogpost=43

V něm jsem uvedl typický příklad, jak můžeme v PHP testovat hodnotu nějaké proměnné:

"
if ( isset($a) and ($a>0) ) {}

Tento zápis je v naprostém pořádku.
Pokud proměnná $a není nastavena,
tak PHP ví, že výsledek závorky bude každopádně false,
proto se už dál nezabývá další podmínkou, tedy netestuje, zda je hodnota $a větší než nula, a vše je v pořádku.

Není potřeba používat zápis
if ( isset($a) ) if ( $a>0 ) {},
protože v praxi oba zápisy vyjdou úplně na stejno.
"

Taková podmínka bude mít výstupní hodnotu true jen v případě,
že testovaná proměnná je nastavena a má testovanou hodnotu.

Ale co když chceme některou možnost použít jako výchozí?

Možností jsou spousty.
Například v případě "switch – case" (v některých jazycích prostě "case") existuje snad ve všech běžných jazycích možnost definovat výchozí možnost,
do níž switch case propadne, když žádná z testovaných možností nevyhověla.

A když se bavíme o běžném "if", příp. v kombinaci s "elseif" a "else",
jistě si poradíte pomocí logického operátoru "or".



// Hlavní sdělení, klíčový obsah, pointa článku

A právě využití "if" a "or", v kombinaci s "isset()", v efektivní podobě zde chci ukázat.
Jde o variaci na dříve uvedený efektivní chvat "if ( isset($a) and ($a>0) )".

Pokud chcete testovat např. zadání GET parametru, který určuje např. režim práce, modul, způsob zobrazení, apod. ve webové aplikaci,
můžete výchozí možnost efektivně definovat takto:

if ( !isset($_GET['mode']) or ($_GET['mode']==1) ) {
// Použije se výchozí režim číslo 1.
}

Je tam isset, aby nenastalo testování nedefinované proměnné.
Je tam definována výchozí volba.


Jak se to bude chovat?

1) Pokud uživatel zvolí ve formuláři volbu ?mode=1,
tak první část podmínky dá po negaci hodnotu false.
PHP engine tedy na základě funkce OR přistoupí k testování druhé části, protože logická funkce OR reaguje i na true v pouhé jediné pod-podmínce.
Mode == 1, takže výsledek bude true, režim č. 1 se použije.

2) Pokud uživatel zvolí ve formuláři volbu ?mode=2,
tak první část podmínky dá po negaci hodnotu false.
PHP engine tedy na základě funkce OR přistoupí k testování druhé části, protože logická funkce OR reaguje i na true v pouhé jediné pod-podmínce.
Mode == 2, takže výsledek bude false, režim č. 1 se nepoužije.

3) Pokud uživatel ve formuláři žádnou volbu nevybere (ani nebyla předvyplněná, a formulář lze odeslat bez vyplnění této volby),
resp. pokud uživatel přišel odjinud než z daného formuláře (např. stránku s formulářem teď právě načetl, a formulář ještě neodeslal),
tedy GET parametr "?mode=" vůbec nebude definován,
tak PHP engine zareaguje už na první část:
Pod-podmínka "!isset($_GET['mode'])" nám po negaci vrátí hodnotu true.
Proto PHP engine už nebude testovat, co je dál za or, a výsledná hodnota celé podmínky "if" bude rovnou true.

A to je to kouzlo.
Isset pro testování, zda je proměnná definována, abychom pak teprve mohli testovat její konkrétní hodnotu,
plní současně funkci defaultní volby pri situaci, kdy proměnná vůbec není definována.



// Pouze pro formuláře v intranetových aplikacích!

4) A co když uživatel zadá neplatnou volbu?

Tento postup neřeší možnost, že se v URL objeví definice se správným názvem atributu, ale neplatnou hodnotou.
Např. ?mode=0 nebo ?mode=990 (pokud správné hodnoty budou např. 1 až 4).

Pokud to v případě dané aplikace nevadí, např. se neaktivuje žádný z výpočtů/výstupů a čeká se na zadání,
a jde o volbu ve formuláři, nejlépe v intranetové databázové aplikaci, kde neřešíme SEO,
tak lze tuto efektivní definici využít.

V případě parsování URL zadaného ručně uživatelem (odkazovaného z jiného webu, mailu, katalogu, ...) nebo v případě veřejně běžících webů by tento postup nebyl dostačující,
tam postupuji jinak, a defaultní zobrazení aktivuji spolehlivě vždy, když nebyla vybrána žádná platná možnost.
Nejlépe ještě před prvním výpisem HTML kódu pomocí "echo", s přesměrováním R=301 na platné URL výchozího zobrazení (menu, nabídky, titulní stránky, ...).



// Bez testování vstupů?

Ano, v příkladu výše používám přímo hodnotu parametru z pole $_GET, tak, jak jsem ji dostal z URL.

Bez ochrany proti SQL injekci, bez testování neplatných hodnot.
Protože zde hodnotu z $_GET nezapisuji do databáze, nekopíruji do jiné proměnné, nepoužívám ve výpočtech, nevypisuji, zkrátka ji nepřebírám jinam.

Bez escapování, protože pro takovéto identifikátory samozřejmě používám jen malá písmena základní latinky, příp. podtržítko, pomlčku nebo číslici. Žádná diakritika, žádná mezera, žádná cyrilice, žádné další znaky.
Jen ho testuji, zda je, anebo není, shodné s mnou určenými hodnotami, o nichž vím, že jsou správné, a že mi neublíží.

Případným cyklem "foreach" nebo funkcí "in_array()" nebo jakkoliv jinak procházím své platné hodnoty, od nich se odpichuji, z nich vycházím, a pak jen porovnávám hodnotu parametru (URL/GET, POST, COOKIES, ...) s platnými hodnotami. To je nejbezpečnější řešení práce se vstupem.
V některých případech případně použiji ještě funkci strtolower() pro převod textového řetězce na malá písmena – typicky v URL, kde předpokládám, že ho zadává ručně uživatel a může se stát, že mi ho zadá verzálkami (velkými písmeny).

Pokud vstupní hodnotu přebíráte a používáte ji jakkoliv jinak než jen pro porovnání v PHP podmínce, je nutné ji ošetřit.
Samozřejmě je kriticky nutné ošetřit jakýkoliv vstup, který posíláte do SQL dotazu (třeba porovnání hodnot na úrovni SQL), aby vám někdo do databáze nepíchl SQL injekci.
Takže v případě porovnání hodnot na úrovni SQL je ošetření nezbytné, jako při jakékoliv jiné práci s SQL v kombinaci s hodnotami od uživatele.



// Dohromady, s dalšími volbami, to bude v PHP kódu vypadat jak?


Takto:

if ( !isset($_GET['m']) or ($_GET['mode']==1) ) $r = 1;
if ( isset($_GET['m']) and ($_GET['mode']==2) ) $r = 2;
if ( isset($_GET['m']) and ($_GET['mode']==3) ) $r = 3;

Zarovnal jsem vám to pěkně pod sebe, abyste viděli,
že první, výchozí, volba se od dalších liší
jednak negací u "isset"
a jednak operátorem "or" místo operátoru "and".
Proto jsem "rezim" zkrátil na $r a "mode" na 'm', aby se podmínky na úzkém blogu nezalomily.



Chování výchozí volby pro režim č. 1 jsem popsal v tomto článku, výše, v těch třech + 1 bodech.



Chování dalších voleb pro další režimy jsem vlastně popsal v tom dřívějším článku, zmíněném a citovaném výše, odkázaném níže;
ale raději ho bleskově shrnu.



Pro druhý řádek zdrojového kódu v ukázce
– testování, zda se má aktivovat režim č. 2:


1) Vstup: ?m=2
Funce "isset()" nám hodí hodnotu true, protože proměnná je definována;
na základě logického operátoru "and" tedy PHP engine otestuje i druhou pod-podmínku,
ta mu také hodí "true", protože je to testovaný režim č. 2,
a tak se režim č. 2 použije.


2) Vstup: ?m=3
Začátek jako v předchozím bodu, první část dá true, protože máme "m" definováno (zadáno);
pokračujeme tedy za operátor "and",
ale druhá pod-podmínka nám hodí hodnotu false, protože 2!=3,
a tak se režim č. 2 nepoužije;
což je správně, když uživatel chce trojku.


3) Vstup: Žádné ?m není definováno
Funkce "isset()" hned na začátku hodí hodnotu false, když ta proměnná není definována,
takže už PHP engine nepotřebuje zkoumat, co je v pod-podmínce za operátorem "and",
když už na beton ví, že výsledek bude tak jako tak false.
Takže netestuje konkrétní hodnotu, nevyskočí žádná chyba, vše je v pohodě.
Přesně jak jsme si podrobně řekli v předchozím článku.
Režim č. 2 se tedy nepoužije.

 

Související odkazy

  


Líbil se Vám článek?


Zpětná vazba – hlasování

Hlasy se na serveru připočítají k počitadlům pro tento článek, např. kolikrát tento článek někoho pobavil a kolikrát tento článek někomu pomohl.

Neukládají se jednotlivá hlasování (vzájemná kombinace hlasů, datum, čas, ani jiné údaje).
Proto nemá smysl odesílat prázdný hlas, nemělo by se co k čemu přičíst.

 

Ve Vašem prohlížeči nebude uložena žádná informace (cookies) o tom, že už jste hlasovali.
- Ve Vašem prohlížeči tedy nebude vidět, jak jste hlasovali.
- Kdykoliv budete moci hlasovat znovu, pokud Vám článek opakovaně pomůže (pobaví Vás, potěší, …).
- Pokud Vás právě u jednoho počítače sedí více, mohou postupně hlasovat další lidé.

Počítám člověkohlasy, nikoliv lidi.
Tedy kolikrát článek někomu pomohl,
nikoliv kolika lidem pomohl
.

Třikrát potěšeného jednoho čtenáře počítám stejně jako tři různé jednou potěšené čtenáře.

Každý má do budoucna neomezený počet hlasů.
Když zapomenete, že jste pro tento článek už hlasovali, nevadí – když Vám někdy v budoucnu bude např. užitečný znovu, tak mu znovu pošlete hlas, že Vám byl užitečný.

Můžete si zvolit 1 až N možností

Štítky, labels, kategorie, témata, tagy, hashtagy

(ve vývoji)
 
#science-technology   #electro-ict    
#languages  
 

Skok nahoru na: Navigační menu
(klávesová zkratka Alt + Shift + horní „5”)

Zaujala Vás tato stránka?

  • Přidat do záložek (Ctrl+D)
  • Sdílet odkaz (vysílačka)Skok nahoru na:
  • Vytisknout (Ctrl+P)
  • Citovat podle ČSN ISO 690

    Tuto stránku

    ADÁMEK, Martin. Osobní blog: Soukromý, neprofesní mikroblog. . Martin Adámek [online]. Náchod / Meziměstí [cit. 2022-12-01]. Dostupné z: https://www.adamek.cz/blog

    Celý web

    ADÁMEK, Martin. Martin Adámek [online]. Náchod / Meziměstí [cit. 2022-12-01]. Dostupné z: https://www.adamek.cz

 

 
 

Národní kulturní dědictví

WebArchiv – Stránky archivovány Národní knihovnou ČR Tyto stránky jsou pravidelně archivovány Národní knihovnou ČR pro svou kulturní, vzdělávací, vědeckou, výzkumnou nebo jinou informační hodnotu za účelem dokumentace autentického vzorku českého webu. Jsou součástí kolekce českých webových stránek, které NK ČR hodlá dlouhodobě uchovávat a zpřístupňovat pro budoucí generace. Jejich záznam je součástí České národní bibliografie a katalogu NK ČR.  

 

 
 

Pro rozptýlení

Bernardýn běžící rychlostí 10 km/h nese pouzdro s 10 disky DVD, každý s daty o velikosti 4,7 GB.
Přenese na trase 8 km data rychleji, než síť Fast Ethernet 100 Mbps?

 

Pro zamyšlení

Nikdy nevěř ničemu, co samo dokáže myslet, pokud nevidíš, kde to má mozek.
[p. Wisley (potažmo J.Rowlingová)]