Autor | Zpráva | ||
---|---|---|---|
Joker Profil |
Autor: Joker
Odkaz na aktuální verzi textu: Základní kurz 16: „Zapovězené“ funkce zveřejněno Odkud se vede diskuse k aktuálnímu stavu textu: První příspěvek po poslední revizi textu Dodělal jsem k základnímu kurzu ještě „dodatkovou“ kapitolu na téma „jak neprogramovat“. Smyslem je informovat začátečníky, že pokud v nějaké staré učebnici, příkladu, atd. tyhle věci uvidí, aby je nepoužívali. Jako obvykle uvítám komentáře a doplnění. |
||
Alphard Profil |
#2 · Zasláno: 14. 2. 2015, 16:05:59
Já bych jednotlivé kapitoly seřadil obráceně. Třeba goto, které máš na prvním místě, je realtivní novinka od 5.3 a jeho použití v návodech vidím opravdu zcela výjimečně. Je to jen vysvětlování, že začátečníci nemají používat něco, co téměř jistě neznají.
Naopak mysql_* a další z konce seznamu jsou na každém kroku, takže by to byla první věc, před kterou bych varoval. |
||
Jan Tvrdík Profil |
Navíc správně použité
goto vede ke zpřehlednění kódu, je to obvykle to nejlepší, co PHP má k dispozici pokud se programátor rozhodne nepoužít výjimky. Viz např. problém popsaný v mém 8 let starém dotazu.
Srovnej následující tři řešení stejného problému: // klasické řešení if (!problémA) { if (!problémB) { if (!problém C) { akce(); foreach (...) { if (!problémD) { if (!problémE) { if (!problém F) { akce2(); } else { $chyba = problémF; break; } } else { $chyba = problémE; break; } } else { $chyba = problémD; break; } } akce3(); } else { $chyba = problémC; } } else { $chyba = problémB; } } else { $chyba = problémA; } if (isset($chyba)) { echo $chyba; } // řešení s DO-WHILE(FALSE) do { if (problémA) { $chyba = problémA; break; } if (problémB) { $chyba = problémB; break; } if (problémC) { $chyba = problémC; break; } akce(); foreach (...) { if (problémD) { $chyba = problémD; break 2; } if (problémE) { $chyba = problémE; break 2; } if (problémF) { $chyba = problémF; break 2; } akce2(); } akce3(); } while (false); if (isset($chyba)) { echo $chyba; } // řešení s GOTO if (problémA) { $chyba = problémA; goto zpracováníChyb; } if (problémB) { $chyba = problémB; goto zpracováníChyb; } if (problémC) { $chyba = problémC; goto zpracováníChyb; } akce(); foreach (...) { if (problémD) { $chyba = problémD; goto zpracováníChyb; } if (problémE) { $chyba = problémE; goto zpracováníChyb; } if (problémF) { $chyba = problémF; goto zpracováníChyb; } akce2(); } akce3(); zpracováníChyb: { if (isset($chyba)) { echo $chyba; } } |
||
Joker Profil |
#4 · Zasláno: 14. 2. 2015, 17:38:51
Alphard:
Já z nějakého důvodu byl názoru, že goto je v PHP už dlouho. I proto ten oddíl je napsaný ve smyslu, že to je jakýsi pozůstatek. V tom případě bych možná část o goto úplně vypustil staré příklady s ním nejsou a že by se to začalo masově používat neočekávám. Jinak ty mysql_* jsou na konci proto, že to beru jako trochu jiný druh problému, než ty ostatní. I když je otázka, jestli to opravdu jiný druh problému je, možná není. Jan Tvrdík: „Navíc správně použité goto vede ke zpřehlednění kódu“
To se občas tvrdí, ale podle mě se to začátečník jen málokdy naučí tak, aby to kód skutečně zpřehledňovalo, a po čase si už zvykne programovat bez goto. „Srovnej následující tři řešení stejného problému“ Já bych asi preferoval jiné klasické řešení: $chyba = problemA ? KOD_A : KOD_OK; if (($chyba == KOD_OK) && problemB) $chyba = KOD_B; if (($chyba == KOD_OK) && problemC) $chyba = KOD_C; if ($chyba == KOD_OK) { akce(); for ($i = 0; ($chyba == KOD_OK) && …) { if (problemD) $chyba = KOD_D; if (problemE) $chyba = KOD_E; if (problemF) $chyba = KOD_F; if ($chyba == KOD_OK) { akce2(); } } } if ($chyba != KOD_OK) { echo $chyba; } Je to jednak kratší, než ty ostatní, ale hlavně to podle mě je přehlednější. |
||
lionel messi Profil |
Joker:
Zdravím, myslím si, že podobný článok môže začiatočníkov odradiť od niektorých najhorších návykov a do koncepcie učebnice sa mi hodí. Možno by som doplnil problematické a (aspoň z môjho pohľadu) neveľmi užitočné superglobálne pole $_REQUEST (o jeho problémoch písal napríklad J. Vrána). Nedávno som v nejakej pomerne novej anglickej knižke o PHP videl niekoľko príkladov, kde bolo toto pole používané na prístup k premenným z formulárov namiesto $_GET /$_POST (nespomeniem si na názov, v prípade záujmu dohľadám).
Taktiež by som zvážil zmienku o už odstránenej direktíve http_long_arrays a s ňou súvisiacim superglobálnym poľom $HTTP_*_VARS , hoci s príkladom používajúcim túto direktívu som sa v aktuálnych zdrojoch ešte nestretol.
|
||
snazimse Profil |
#6 · Zasláno: 14. 2. 2015, 18:50:29
Joker
Hodně dobrý článek, super! No magic_quotes_gpc je z toho určitě největší šílenost. S tím bylo tolik problémů. |
||
Tomáš123 Profil |
#7 · Zasláno: 14. 2. 2015, 18:52:04
Joker:
Chcel by som sa opýtať na funkciu eval() . Aj po prečítaní príslušného oddielu v článku mi stále nie je jasné, prečo je táto funkcia tak nebezpečná. Prečo stále upozorňujete na jej nepoužívanie najmä začiatočníkov? Aké problémy môžu nastať vplyvom jej nesprávneho použitia?
K článku nemám čo povedať, ale myslím, že táto otázka s ním okrajovo súvisí a po vyjasnení by sa tam mohli lepšie špecifikovať nevýhody používania tejto funkcie. |
||
snazimse Profil |
Tomáš123:
Myslím, že je to tím, že může sloužit jako dobrý přístup dovnitř webu.Uživatel tam může cokoliv vložit viz:článek. |
||
tiso Profil |
#9 · Zasláno: 14. 2. 2015, 23:02:25
ad premenné premenné, čo toto:
list($controller, $method, $params) = $router->match(); $c = new $controller(); $c->$method($params); foreach($this->observers as $obs) { $obs->update($this); } |
||
Kubo2 Profil |
#10 · Zasláno: 15. 2. 2015, 00:49:00
tiso:
Až na to, že v tom príklade s poslucháčmi premenné premenné vôbec nepoužívaš. :-) |
||
Chro. Profil |
V článku chybějí zmínky o zapovězených funkcích ereg, eregi, ereg_replace a eregi_replace.
EDIT: A o mém oblíbeném while(true) :) |
||
Joker Profil |
Upravil jsem článek:
Ad [#2], [#3], odstranil jsem část o goto ([#4]: „V tom případě bych možná část o goto úplně vypustil staré příklady s ním nejsou a že by se to začalo masově používat neočekávám.“) lionel messi [#5]: O existenci $_REQUEST se v základním kurzu mluví, možná bych přidal spíš zmínku tam. Navíc jsem ho viděl používat jen sporadicky. edit: Přidal jsem zmínku do kapitoly o polích. Ad $HTTP_*_VARS : „hoci s príkladom používajúcim túto direktívu som sa v aktuálnych zdrojoch ešte nestretol.“ - no právě, ani já ne. Asi nebude potřeba na to upozorňovat.
Tomáš123: „Aj po prečítaní príslušného oddielu v článku mi stále nie je jasné, prečo je táto funkcia tak nebezpečná.“ Popis jsem rozšířil. Je to teď lepší? Chro.: „V článku chybějí zmínky o zapovězených funkcích ereg, eregi, ereg_replace a eregi_replace.“ Přidal jsem je k části o Mysql (která se tím změnila spíš na „zastaralá rozšíření“). |
||
juriad Profil |
#13 · Zasláno: 15. 2. 2015, 09:55:35
Joker:
Trochu bych se snažil čtenáře přesvědčit, že dokumentace je ten správný zdroj informací (na rozdíl od různých rádoby zkušených blogů na webu). Zkušení uživatelé, pokud si nejsou jistí, se jsou podívat do oficiální dokumentace. Připiš také poznámku, že oficiální dokumentace často obsahuje varování ohledně používání zavržených nebo nebezpečných funkcí a rozhodně by se neměly brát na lehnou váhu. Jiné funkce (addslashes) varování v rámečku neobsahují, ale je obsaženo v samotném textu. |
||
Tomáš123 Profil |
#14 · Zasláno: 15. 2. 2015, 11:35:58
Joker:
„Je to teď lepší?“ Áno, teraz rozumiem, nebezpečenstvu. Keď ale nahliadneme do oficiálnej dokumentácie, vidíme príklad, kde mi príde použitie funkcie eval() úplne zbytočné. Ak by pochádzali dve premenné definované na začiatku od užívateľa, vieme rovnakého efektu dosiahnuť (iba) použitím úvodzoviek pri definovaní premennej $str . Vlastne by ju ani nebolo treba definovať...
Načo teda toľko nebezpečenstva okolo? Kedy je použitie tejto funkcie naozaj potrebné? |
||
Alphard Profil |
Tomáš123 [#14]:
Někdo by eval() mohl chtít použít třeba na vyhodnocení matematického výrazu místo toho, aby správně použil matematický parser. Uživatel má třeba zadat 2*(4+5) , tento výraz se má (bezpečně) vyhodnotit pomocí eval(), jenže pak přijde zlý uživatel a vloží tam kód např. copy('http:...', 'hack.php') . Pokud se mu to podaří zapsat tak, aby nezpůsobil syntax error, funkce to vykoná, nahraje na server útočníkův php script a ten získá plný přístup k webu.
Kromě bezpečnostního hlediska to často ukazuje na špatný návrh. Umím si představit třeba nějaké helpery uložené v databázi, které chci dynamicky vykonávat. Ale ve chvíli, kdy mám nějaký kód mimo prostor, kam mi dosáhne IDE, mám při refaktoringu problém :-) Joker: Ano, je to lepší, aspoň dle mého názoru. Hezké. |
||
Jan Tvrdík Profil |
Tomáš123:
Funkce eval má i jiné než bezpečností problémy, např. je praktické nemožné debuggovat chybu, která při provádění evalu nastane.
„Kedy je použitie tejto funkcie naozaj potrebné?“ Když potřebuješ spustit dynamicky generovaný kód z paměti. Hodí se to např. na dynamické sestavování tříd za běhu, což používají mockovací nástroje. Normální programátor (tm) to nepotřebuje vůbec nikdy a pokud má pocit, že to potřebuje, tak téměř určitě má špatně navrženou aplikaci a celý problém je řešitelný lépe. Joker: Reakce na „Svého času jsem se dokonce snažil přijít na nějaký scénář, který by nějak ospravedlnil použití proměnných proměnných. Na nic jsem nepřišel.“ z vedlejšího vlákna, kde nechci motat začátečníkům hlavu: Hodí se to tam, kde bys normálně použil extract (příklad), ale je pro tebe kritická efektivita. Funkce extract totiž bohužel v PHP < 7.0.0 nepoužívá copy-on-write, takže spotřebuje děsně moc paměti, viz github.com/nette/nette/pull/1225 a 3v4l.org/e8psv
|
||
Jan Tvrdík Profil |
#17 · Zasláno: 15. 2. 2015, 15:01:10
Jinak bych asi rovnou zmínil
md5 a sha1 pro hashování hesel (pro jiné účely jsou většinou v pohodě). V době, kdy má endora i wedos k dispozici PHP 5.5 tak lze začít důrazněji doporučovat password_* funkce.
|
||
snazimse Profil |
#18 · Zasláno: 15. 2. 2015, 21:53:13
Jan Tvrdík:
Co doporučuje, dneska používat? Bcrypt? Nebo jak jste uvedl doporučení funkce v php password_hash? Díky! |
||
lionel messi Profil |
#19 · Zasláno: 15. 2. 2015, 21:56:55
snazimse:
„Nebo jak jste uvedl doporučení funkce v php password_hash?“ Druhú menovanú funkciu. Bolo by vhodné sa v tomto vlákne striktne držať témy (vývoj učebnice PHP) a nerobiť z neho priestor na všeobecnú diskusiu. |
||
Jan Tvrdík Profil |
#20 · Zasláno: 15. 2. 2015, 22:09:06
snazimse:
password_hash ve výchozím používá bcrypt, je to vlastně jenom crypt s hezčím API.
|
||
snazimse Profil |
#21 · Zasláno: 15. 2. 2015, 22:57:42
lionel messi
Jj určitě konec diskuze. Jan Tvrdík: Děkuji! |
||
Časová prodleva: 9 let
|
0