Popisovat vadný OOP model v PHP4, který objekty místo předávání
kopíruje, snad netřeba. Pokud nevíte, o čem hovořím, mrkněte do dokumentace.
Tato nepříjemnost se řeší naužíváním znaku &
.
Ten je potřeba použít při:
- vytváření objektu
$object = &new MyClass()
- přiřazení objektu
$objectB = & $objectA
- předávání objektu funkci
function doIt(& $object)
- vracení objektu funkcí
function &getInstance()
- a volání takové funkce
$object = &getInstance()
Při předávání objektu funkci navíc přicházíme o možnost určit
výchozí hodnotu – nelze psát
function doIt(&$object = null)
a komplikuje se vkládání
přímých hodnot – doIt('ahoj')
je třeba psát jako
doIt($var = 'ahoj')
. V některých případech ani
&
nepomůže (např. list() nebo foreach) a je třeba použít
speciální konstrukce.
Programátor v PHP4 se s tím naučil žít. Jenže přišlo PHP 4.4.0 a to mu hodilo další klacek pod nohy. Následující konstrukce nově generuje chybu Notice: Only variable references should be returned by reference.
function &factory()
{
return new MyClass();
}
A jako správné se považuje
function &factory()
{
$php_4_sucks = &new MyClass();
return $php_4_sucks;
}
Tedy jako běžné se stanou tyto konstrukce
$false = false; return $false;
. To je mazec, co?
Co to zkusit zcela jinak?
Docela dlouho jsem přemýšlel, jak celou tu ampersárdnu elegantně obejít. Jak psát PHP5-like skripty, aby jim čtverka rozuměla. Něco mě sice napadlo, ale je to stále řešení na půl cesty.
Aktualizováno 5. 8. 2005
Zde publikovaný způsob jsem nakonec zavrhl a vymyslel elegantnější řešení, viz spot PHP4: zbavme se ampersandů II.
Komentáře
rarous #1
asi bych se na to vykašlal a odešel od PHP ;) Ale takový řešení asi nečekáte, že?
Mark #2
#1 rarousi, k MS Windows only ASP ? ne tak na takove rozhodnuti bych musel byt s PHP opravdu hodne nespokojeny (nechat si ufiknout kridla jen pro prislib cersvejsiho vzduchu:-) navic sve skripty v novych projektech uz takrka vyhradne nasazuji PHP5 preprocesor namisto ctyrkovych verzi, a to je uz trochu jine kafe ..
rarous #3
:)) o ASP nemluvim… .net je úplně něco jinýho a navíc neni Windows only, ale, komentář jsem nepsal kvůli flame ;) spíš jako pobavení.
Jinak jsem rád, že se někdo zajímá o OOP v PHP a Davidova práce se mi opravdu líbí, je vidět, že je to člověk, kterej tomu rozumí, takových by bylo potřeba mnohem víc ;)
Prosím, nereagujte na tento komentář ohledně .netu
Arthur Dent #4
Je jistě spousta jiných řešení. Třeba Python. Nebo PERL – jediný jazyk, u kterého zdrojové kódy programů vypadají stejně, i když je zašifrujete algoritmem DES3.
Ale PHP je asi jediný „normální“ skriptovací jazyk, kde „normálním“ myslím „vypadající jako C nebo Pascal“.
S ASP jsem chvíli dělal. Asi rok. A po pravdě řečeno – ono vás brzy přestane bavit, když na každou kravinu potřebujete nějakou WIN komponentu a zjistíte, že ty WIN komponenty jsou v 90% případů „commercial“.
Po pravdě řečeno – proti výhodám ASP jsou ty nejhorší vlastnosti PHP ještě pořád skvělé.
Nai Dzet Quiv #5
Hmm, a to jsem včera „upgradoval“ na PHP 4.4.0 (s PHP5 jsem se ještě nestačil obeznámit 🙂 ).
David Bures #6
#4 Arthure Dente, on uz to psal rarous, ale rozdil mezi ASP a .NETem je asi takovy jako mezi programovanim a psanim skriptu ;)
Arthur Dent #7
#6 Davide Buresi, Ono to totiž není na první pohled vidět, ale já reagoval na 1 a 2. Když se podíváš na čas přidání příspěvku, tak zjistíš, že jsme s Rarousem reagovali nastejno… Takže teď už ti možná došlo, že nepíšu o .NET, ale o ASP. A to mi připadá blbé, ať už jej pohání JScript, VBScript, C#, J# nebo command.com…
rarous #8
Doporučuju přečíst něco o projektu MONO, nebo o projektu Phalanger, možná vám to pomůže rozšířit si obzory… Ostatně samo PHP5 se snaží ASP.NET nebo JSP dohnat nebo alespoň se jimi inspirovat… ;)
David Grudl #9
Prosím, ukončete debatu o jiných jazycích než je PHP.
Snažím se rozlousknout způsob, jak dnes psát v PHP4 skripty, které za cca půl roku snadno přehodím na PHP5 – tedy rád bych se zbavil ampersandů. Uvedený nástin v článku ukazuje, že to teoreticky lze. Pokud budete mít nějaký nápad k tématu, neváhejte jej napsat.
markon #10
PHP4 i PHP5 má ještě jednu naprosto bezvadnou vlastnost, když si přečteš hodnotu hlavičky IF_MODIFIED_SINCE, tak po druhé ji nelze přečíst, třeba
echo $_SERVER[‚IF_MODIFIED_SINCE‘];
echo $_SERVER[‚IF_MODIFIED_SINCE‘];
vydává v PHP opravdu zajímavý výstup. Nebo ideální je
if(empty($class->$fce()))
taky nejde a navíc je to prý vpořádku
PHP má spoustu bugů, ale oproti jiným programovacím jazykům je znatelně lepší.
Jakub Vrána #11
#10 markone, Asi jste měl na mysli spíš
$_SERVER["HTTP_IF_MODIFIED_SINCE"]
. Za jakých okolností se tahle chyba projevuje? Mě se ji nepodařilo zreprodukovat.Mimochodem, lepší místo pro hlášení takovýchto chyb je https://web.archive.org/….php.net:80/.
Ebo #12
Já bych radši zase čmáral omalovánky 🙂
rane #13
#9 Davide Grudle, no ja mam napad: pol roka nerob nic, a potom mozes rovno pisat v php 5 :)
David Grudl #14
#13 rane, Ani nevíš, jak rád. Půl roku bych nedělal nic a pak bych si to zopakoval ;)
Michal #15
No neřekl bych, že je to chyba jako taková, když se to hlásí jako Notice: Only variable …
Sice jsem to nezkoušel, ale script se nezastaví a normálně se provede, ne?
David Grudl #16
#15 Michale, jde o chybovou hlášku úrovně E_NOTICE, tedy nepozastaví vykonávání skriptu.
lukas #17
A nevite, jak se zbavit toho $false = false; return $false? Mam treba funkci, ktera mi nacte parametr modulu v CMS (coz muze tahat ze spousty mist jako XML, databaze nebo HTTP query – zalezi to na situaci). Ten parametr se tedy musi vracet pres referenci (protoze je to nekdy velka promenna). Ale potrebuju mit taky moznost, aby ta funkce umela rict „smula kote, zadny parametr nebyl zadan“ a vratit false. Jedine me napadlo deklarovat promenou $false jako globalni, to bych sice pak uz mohl psat trosku hezci „return $false;“ jenze zase bych si ji musel ve funkci zavolat pres global $false;
David Grudl #18
#17 lukasi, Ten parametr se tedy musi vracet pres referenci (protoze je to nekdy velka promenna).
PHP má kopírování proměnných celkem vychytané a fyzicky k němu nedojde, dokud se jedna z proměnných nezmění. Třeba tento příklad až do posledního kroku si vystačí s 10MB RAM:
Zajímavé je také to, že předávání referencí je v podobných případech dokonce pomalejší! Pokud byste v uvedeném příkladě deklaroval funkci jako test(&$var), vykonávání by bylo 10.000× pomalejší. Ale to je samozřejmě extrém…
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.