Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

PHP 4.4.0 krokem zpátky + skorotrik

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

  1. rarous http://rarous.aspweb.cz #1

    avatar

    asi bych se na to vykašlal a odešel od PHP ;) Ale takový řešení asi nečekáte, že?

    před 11 lety | reagoval [2] Mark
  2. Mark #2

    avatar

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

    před 11 lety
  3. rarous http://rarous.aspweb.cz #3

    avatar

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

    před 11 lety
  4. 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é.

    před 11 lety | reagoval [6] David Bures
  5. 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 :-) ).

    před 11 lety
  6. David Bures http://www.websky.cz #6

    #4 Arthure Dente, on uz to psal rarous, ale rozdil mezi ASP a .NETem je asi takovy jako mezi programovanim a psanim skriptu ;)

    před 11 lety | reagoval [7] Arthur Dent
  7. 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…

    před 11 lety
  8. rarous http://rarous.aspweb.cz #8

    avatar

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

    před 11 lety
  9. David Grudl http://davidgrudl.com #9

    avatar

    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.

    před 11 lety | reagoval [13] rane
  10. markon http://blog.air4web.com/ #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ší.

    před 11 lety | reagoval [11] Jakub Vrána
  11. Jakub Vrána http://php.vrana.cz/ #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 http://bugs.php.net/.

    před 11 lety
  12. Ebo #12

    Já bych radši zase čmáral omalovánky :-)

    před 11 lety
  13. rane http://metatribe.org #13

    #9 Davide Grudle, no ja mam napad: pol roka nerob nic, a potom mozes rovno pisat v php 5 :)

    před 11 lety | reagoval [14] David Grudl
  14. David Grudl http://davidgrudl.com #14

    avatar

    #13 rane, Ani nevíš, jak rád. Půl roku bych nedělal nic a pak bych si to zopakoval ;)

    před 11 lety
  15. 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?

    před 11 lety | reagoval [16] David Grudl
  16. David Grudl http://davidgrudl.com #16

    avatar

    #15 Michale, jde o chybovou hlášku úrovně E_NOTICE, tedy nepozastaví vykonávání skriptu.

    před 11 lety
  17. lukas #17

    avatar

    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;

    před 11 lety | reagoval [18] David Grudl
  18. David Grudl http://davidgrudl.com #18

    avatar

    #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:

    function test($var) {
      return $var;
    }
    
    // alokuj 10MB
    $s1 = str_repeat('a', 1e7);
    
    $s2 = test($s1); // nějaká činnost
    
    // stále je fyzicky alokováno jen 10MB!
    
    $s2{1} = 'b';  // změníme proměnnou
    
    // teprve nyní je zabráno 20MB

    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…

    před 11 lety

Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.