Co bych v PHP navrhl jinak

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

PHP považuji za poměrně dobře navržený jazyk s obstojnou vnitřní logikou. Kdybych ale mohl, některé věci bych udělal jinak a myslím, že většina vývojářů PHP (těch, kteří ho v současnosti vyvíjí) by mi dala zapravdu.

V první řadě bych zrušil některé direktivy – register_globals, magic_quotes_gpc, magic_quotes_runtime, register_long_arrays, safe_mode, open_basedir a možná ještě některé další. Chápu, proč je jazyk obsahuje, některé z nich sám i používám, ale pravda je taková, že většinou přináší víc starostí než užitku. register_globals se hodilo pro psaní triviálních skriptíků posílajících data z formuláře mailem, magic_quotes_gpc se snaží ochraňovat lidi, kteří neví nic o SQL Injection, magic_quotes_runtime je podle mě jenom do počtu, protože ve výchozí konfiguraci je vypnuté a zapne si ho účelově jenom ten, kdo o problematice něco ví, dlouhá pole jsou přežitek z historie a bezpečnost webového serveru by měla být zajištěna na úrovni operačního systému a ne v PHP.

S těmito direktivami si vývojáři PHP pěkně naběhli, přestože se jenom snažili vyjít lidem vstříc a nabídnout jim jednoduchá řešení jejich problémů (magic_quotes_gpc nebo safe_mode). Jazyk se tím podle mě ale „umazal“ a většina vývojářů PHP toho teď lituje. Cesta zpět ale v podstatě už neexistuje – spousta skriptů na tyto direktivy spoléhá a pokud se starší verze PHP mají někdy přestat podporovat, je potřeba zpětnou kompatibilitu zachovat.

Jeden z dalších velkých nesmyslů je překlad neexistujících konstant na řetězce – když napíšete $row[id] a konstanta id neexistuje, použije se její textová podoba, tedy "id". Nevím přesně, kdy se tahle prasárna v PHP objevila, ale řekl bych, že to také byla úlitba pohodlným pisálkům kódu.

Když bych měl při navrhování PHP volnou ruku, zvolil bych také konzistentní pojmenování funkcí. Začátečníky bez pořádného editoru (který neukazuje seznam existujících funkcí) mate, že existuje funkce str_replace a zároveň strpos. U extenzí se to většinou už podařilo sjednotit, databáze navíc používají podobné názvy funkcí (místo pg_exec už je pg_query, byť první jmenovaná stále existuje), není to tak ale všude – např. funkce pro práci s obrázky jsou stále bez podtržítka. Opět chápu, kde se tato nejednotnost vzala – PHP má spoustu funkcí převzatých z jiných jazyků a v zájmu jednoduššího přechodu je převzalo i s jejich názvy.

Zrušil bych také rozličné alternativní syntaxe – # komentáře, uzavírání bloků do : end, tři nadbytečné způsoby obalování PHP kódu nebo spouštění příkazů přes operátor `.

Byť nejsem horlivým zastáncem objektů, tak musím říct, že některým rozšířením by více slušelo objektové rozhraní – určitě např. databázím, obecně těm, které jako parametr používají resource objektu, se kterým pracují (např. již zmiňované funkce pro práci s obrázky). Nejsem ani horlivým zastáncem výjimek, ale když už v jazyku jsou, možná by bylo lepší je používat místo chyb.

A když bych PHP dělal sám pro sebe, asi bych nařídil povinné uzavírání bloků kódu do {}, u zastánců co nejkratšího kódu bych se ale asi nesetkal s pochopením.

Všechno to je jen „co by, kdyby“, čas už se prostě vrátit nedá. Navíc, o čem bych potom psal…

P.S.: Po napsání článku jsem si přečetl příspěvek Rasmuse Lerdorfa (původního tvůrce PHP) o změnách navrhovaných do PHP 6.0. Zjevně nejsem jediný, komu tyto věci leží v žaludku, shoda mezi vývojáři je až neuvěřitelná (viz navazující příspěvky). Časem bychom se tedy mohli dočkat PHP s polovinou současných WTF vlastností.

Jakub Vrána, Ze zákulisí, 15.8.2005, diskuse: 34 (nové: 0)

Diskuse

mol:

A bylo někdy vůbec navrženo? Já měl dojem, že ta syntaxe vznikla jako zjednodušená verze syntaxe Perlu na kterou pak se pak lepilo, co zrovna koho napadlo :-)

Oswald:

V tom příspěvku od RL je také dost zajímavé:

7. Make identifiers case-sensitive

Gimli2:

2oswald: Me osobne by to nevadilo. Ale kvuli zpetne kompatibilite a lenosti az blbosti nekterych programatoru to asi jen tak nebude.

ales:

http://www.root.cz/zpravicky/zacalo-sa-pracova…-verzii-php/

Jak se zdá, některá přání budou splněna ve verzi 6 (citace):
* Úplné odstranění register_globals
* Úplné odstranění magic_quotes_xxx
* Filtrování vstupních dat
* Zahrnutí opcode cache přímo do jádra PHP (uvažuje se o APC)
* Odstranění safe_mode ve prospěch open_basedir a vylepšení jeho funkčnosti
* Odstranění vlastností které byly označené jako zavrhnuté v PHP 3/4

johno:

No, ja by som už konečne chcel mať v PHP packages. Lebo s kolíziami mien tried sa ďaleko nedostaneme. Polovičné riešenia, ako to má vymyslené napríklad PEAR moc neberem.

ikona Radek Hulán:

Hm, co je špatného na safe_mode? A open_basedir jej má nahradit? To přece nejsou zaměnitelné věci, používají se současně..

ikona Jakub Vrána OpenID:

Problém se safe_mode je především v tom, že se špatně používá. Bližší rozbor viz http://php.vrana.cz/bezpecnost-weboveho-serveru.php. Prvotní otázka je, proč by něco takového mělo být v PHP, když stejně zabezpečené by měly být i ostatní skriptovací jazyky a měla by to tedy být věc přinejmenším nastavení zabezpečení webového serveru, spíše ale rovnou operačního systému.

tom:

Jeden z dalších velkých nesmyslů je překlad neexistujících konstant na řetězce - když napíšete $row[id] a konstanta id neexistuje, použije se její textová podoba, tedy "id". Nevím přesně, kdy se tahle prasárna v PHP objevila, ale řekl bych, že to také byla úlitba pohodlným pisálkům kódu.

jedna z moznosti psani kodu u problematiky SQL injection:
<?php
// spolehnutí se na magic_quotes_gpc
mysql_query("SELECT * FROM tabulka WHERE nazev = '$_GET[nazev]' OR id = '$_GET[id]'");
?>

Myslim, ze presne zde se ta prasarna vzala.

ikona Jakub Vrána OpenID:

Uvnitř řetězce identifikátor s konstantou nekoliduje a takovéto použití je tedy naprosto v pořádku. Nicméně se to opravdu asi vzalo odtud, když se lidi ptali: "A proč mohu psát "Ahoj $a[b]" a nemohu psát $a[b] mimo řetězec?" Tedy opravdu úlitba.

Jakub Podhorský:

já si myslím že spíš některá z příštích verzí PHP by neměla vsázet na zpětnou kompatibilitu ale spíš na odstranění těchto nesmyslů

a kdo bude chtít bude používat starou verzi a kdo tyhle nesmysli už nechce trpět tak jednoduše novou...podobně je to přece i s PHP pokud pracuju s objektama a chci jejich lepší podporu jednoduše dělám v PHP5 ale musím spoléhat že můj kód už nebude zpětně kompatibilní pokud využiju většinu nových vlastností

ikona Jakub Vrána OpenID:

Zpětná kompatibilita znamená to, že skripty ze starších verzí poběží i v nové verzi. Ne to, že skripty napsané pro novou verzi poběží i ve staré.

Jakub Podhorský:

jojo to jsem měl na mysli akorát jsem to nejspíš blbě napsal :)

markon:

Jen by mě zajímalo, jak by si bez open_basedir provozoval hosting? Tohle je právě jedna z nejužitečnějších dirakretiv, která umožní bezpečně provozovat desítky i stovky webů na jednom serveru.

ikona Jakub Vrána OpenID:

Navržené řešení je popsáno na http://php.vrana.cz/bezpecnost-weboveho-serveru.php. Na open_basedir mi vadí především to, že PHP nezaručuje, že všechny jeho komponenty budou tuto direktivu respektovat, tudíž může navodit falešný pocit bezpečí.

michal:

co treba fcgi?

David Majda:

Já bych k seznamu "co udělat jinak" přihodil ještě dvě věci:

* zrušit podtržítkovou mánii: $_GET, $_POST, __sleep, __wakeup, ...

* zrušit povinnost oznamovat přístup ke globálním proměnným přes "global" - strašně to zdržuje a vede k chybám, zejména když člověk uzavírá kod původně z "top level" do funkce

tom:

proc zrusit $_GET,$_POST ?

na jednu stranu chces zrusit superglobalni promenne a na druhou chces aby se nemuselo uvadet u pouziti globalnich 'global'.

To je vysada prave superglobalnich promenych a myslim, ze prave nutnost pouziti global vede k vyssi bezpecnosti.

David Majda:

Nepochopil jsi mě správně, mě vadí jen ta podtržítka na počátku názvů běžně používaných proměnných/funkcí. Podtržítka odjakživa označovala něco interního, na co by normální programátor neměl sahat, proto podle mě třeba u $_GET a $_POST nemají co dělat.

tom:

to mas asi pravdu. Tezko rict jaky duvod meli vyvojari aby to tak udelali. Mozna prave tim chteli odlisit tento druh promenych od tech, ktere si vytvori sami programatori.

Jakub Podhorský:

jojo s tím souhlasím i když u superglobálních proměnných mi to až tak nevadí...ale věci jako __sleep, __wakeup, __construct, __destruct, __get, __set, __call, __clone a možná ještě dál a dál :) jsou děsný

Tomáš (ATom):

Určítě to udělali právě proto, aby nedošlo ke kolizi s již existujícími programy, kde se právě metody jako set() a get() mohou vyskytovat a protože bylo v PHP zvykem _ začínat metody které jsou private, přidali tam autoři projistotu hned dva podtržítka.

Jakub Podhorský:

to sice jo ale já nechápu co pořád všichni mají se zpětnou kompatibilitou....stejně to jednou dojde k tomu že prostě už něco kompatibilního nemůže být a prostě s tím přestanou takhle se tyhle nesmysli akorát táhnou zbytečný roky

já to beru zpětná kompatibilita je důležitá věc ale podle mě jen do určitý míry...v PHP4 to beru a proč do PHP5 natahly tyhle kraviny stejně se musela polovina(tohle není konkrátní údaj, tak to berte s rezervou) tříd z verze 4 přepsat nebo alespoň mírně poupravit pro verzi 5

tark:

Zrušit "global $CONF" mě osobně příde jako pěkná volovina - neodliším tím proměnný ve funkci a když budu využívat cizí fce, tak ... narazím.

ikona spaze:

ja bych tu podporu pro global zrusil uplne ;) stejne jsem to snad nikdy nepouzil, vstup do fce/metody pres parametry, vystup pres return, v OOP pak pres $this, self. Co vic chtit, potrebovat ;)

Jakub Podhorský:

popřípadě z funkcí ještě pomocí referencí :)

ikona Jakub Vrána OpenID:

Ani k jednomu názoru se nepřikláním:

Podtržítka jsou použita jednak z důvodu zpětné kompatibility, hlavní důvod je ale v odlišení od normálních metod. U __sleep() je na první pohled vidět, že se jedná o něco speciálního, u sleep() by to nebylo vidět ani náhodou a u _sleep() taky ne, protože to bylo zvykem používat pro privátní metody.

To, že jsou funkce defaultně izolované od globálních proměnných, je vlastnost k nezaplacení. Nechtěl bych vidět ten zmatek, kdyby tomu bylo jinak. Spíš bych se přikláněl k názoru spazeho, zrušit global úplně. Pak bych ale také např. ocenil, aby konstanty mohly obsahovat pole.

ikona dgx:

Tuším, že ActionScript nemá ve funkcích izolované globální proměnné. A je to děs!

Honza Odvárko:

A to já bych zase na PHP změnil pravidla pro require a include, a to tak, že by hledaly soubory relativně k dirname(__FILE__), místo k umístění běžícího skriptu.

Ale takovou laskavost mi vývojáři PHP mesi setinkovými verzemi asi neudělají :)

ikona Jakub Vrána OpenID:

Relativně k běžícímu skriptu se soubory nehledají. Hledají se relativně k aktuálnímu adresáři (getcwd) a potom právě relativně k __FILE__.

Honza Odvárko:

> Hledají se relativně k aktuálnímu adresáři

To je vlastně pravda, když on bývá nastaven právě podle umístění skriptu - tak to už beru jako samozřejmost.

> a potom právě relativně k __FILE__

To se mi nezdá... ne spíš k $_SERVER['SCRIPT_FILENAME'] ?

ikona Jakub Vrána OpenID:

Když se ti to nezdá, tak se podívej do dokumentace nebo si to vyzkoušej. Do diskuse pokud možno uváděj spíš fakta než pocity.

Honza Odvárko:

Taky že jsem se kouknul, chtěl jsem ti tím taktně naznačit že píšeš kraviny.
> Files for including are first looked for in each include_path entry relative to the current working directory, and then in the directory of current script.

Bohužel jsem fakta pochopil špatně, protože jako current script chápu skript volaný v požadavku.

Takže ti dlužím omluvu.

ikona Jakub Vrána OpenID:

Taky ses rovnou mohl podívat, kdo to do té dokumentace napsal :-) - http://cvs.php.net/phpdoc/en/language/control-…&view=markup

Honza Odvárko:

No dobře to bych se taky naštval. Já to ale fakt jen pochopil špatně, již prosím ne více kopanců do bezbranného a dokumentaci sledujícího.

Diskuse je zrušena z důvodu spamu.

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