Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

PHP 5.4 má nepoužitelný typ callable

Jednou z novinek PHP 5.4 je typehint callable. Byla by to parádní věc, kdyby to tvůrci tak děsně nezprasili.

PHP typ callbable je pseudotypem, jehož hodnotou může být buď název metody či funkce (tj. řetězec) nebo dvojice třída/objekt a její metoda, tedy pole. V PHP se používá od pradávna, nicméně od verze 5.4 pro něj existuje typehint:

class Template
{
    function registerHelper($name, callable $helper)
    {
        ...
    }
}

$template = new Template;
$template->registerHelper('date', 'Helpers::date');

Skvělé. Tedy až do chvíle, než to vyzkoušíte a PHP vás zdupne:

error:  Argument 2 passed to Template::registerHelper() must be callable, string given

Aha, tak je to asi potřeba zapsat jako pole:

$template->registerHelper('date', ['Helpers', 'date']);

Výsledek je opět:

error: Argument 2 passed to Template::registerHelper() must be callable, array given

Ve skutečnosti PHP vadí to, že třída Helpers neexistuje. Totiž už během volání registerHelper její přítomnost vyžaduje. Typehint callable, narozdíl od všech jiných typehintů, neověřuje jen formální platnost předaného argumentu, ale ujišťuje se, že uvedená třída skutečně existuje a má zmíněnou metodu. Pokud třída neexistuje, pokusí se ji načíst autoloadingem.

Což jednak zabíjí lazyloading – už samotné předání parametru s callbackem načte příslušnou třídu, která by se třeba jinak vůbec načítat nemusela.

A za druhé to generuje naprosto idiotské chybové hlášky. Což je věc, na kterou jsem dosti citlivý. Ze zprávy must be callable, string given těžko někdo pochopí, že typ string je použitý správně, jen neexistuje třída či metoda. Já bych to chápal tak, že funkce neakceptuje řetězce. Přitom třeba funkce call_user_func ve stejné situaci generuje zcela smysluplné chyby jako:

Warning: call_user_func() expects parameter 1 to be a valid callback, class 'Helpers' not found

Warning: call_user_func() expects parameter 1 to be a valid callback, class 'Helpers' does not have a method 'date'

Na chybu jsem upozornil, bohužel Rasmus je se současným chováním nadmíru spokojen. Setrvávat na zavádějících chybových hláškách je projevem arogance a hlouposti: namísto opravy raději uvedou ve zmatek statisíce programátorů a připraví je o spoustu času. Nette Framework rozhodně zprasený typ callable používat nebude.

Komentáře

  1. paranoiq #1

    avatar

    já prostě všude vyžaduji Nette\Callback. je to režie navíc (vytvoření jednoho objektu), ale dá se na to spolehnout a funguje to všude. nejen v 5.4. možná by v tomhle ohledu mohlo přitvrdit i Nette… nebo radši ne? (to by bylo BC breaků)

    před 4 lety | odpovědět
  2. Jiří Soukup #2

    Nechce se ti někdy přesedlat na jazyk, kde je koncentrace kreténů v core přeci jen menší? Obdivuji tvou trpělivost :)

    před 4 lety | odpovědět | reagoval [4] Pitrsonek
  3. Filip Procházka (@HosipLan) #3

    avatar

    Davídek je skrytý masochista, jako i my všichni :)

    před 4 lety | odpovědět
  4. Pitrsonek #4

    #2 Jiří Soukupe, Na co treba presedlat?

    před 4 lety | odpovědět | reagoval [5] enumag [6] softice
  5. enumag #5

    avatar

    #4 Pitrsonku, Co třeba na Haxe? Dá se zkompilovat mimo jiné i do PHP. ;-)

    před 4 lety | odpovědět
  6. softice #6

    avatar

    #4 Pitrsonku, Clojure, Erlang, F#, Haskell, Javascript, Scala, Kotlin, Go, D v poslednej dobe vzniká mrte zaujimavých jazykov, stačí si len vybrať.

    před 4 lety | odpovědět | reagoval [7] jlk
  7. jlk #7

    avatar

    #6 softice, Javas…wat?

    Ano, je možné psát s diakritikou :-(

    před 4 lety | odpovědět
  8. Tori #8

    avatar

    Ještě by to šlo vysvětlit tak, že „callback“ !== „callable“, že callback musí být pouze syntakticky správný, kdežto callable i spustitelné. Ale pak by kromě is_callable (s implicitním autoloadingem) měla existovat i funkce is_callback (jen ověření syntaxe). Anebo naopak v zájmu konzistence k is_string přidat přepínač, aby akceptovala i desetinná čísla a objekty s metodou __toString.

    před 4 lety | odpovědět | reagoval [9] David Grudl
  9. David Grudl http://davidgrudl.com #9

    avatar

    #8 Tori, Pro ověření syntaxe lze použit is_callable($var, TRUE)

    před 4 lety | odpovědět
  10. juzna.cz http://juzna.cz #10

    avatar

    Nezkoušel jsi, jaký dopad na výkonnost aplikací by mělo použítí callable v Nette? Byl by to opravdu problém? Kolik tříd by se muselo načíst „zbytečně“ (rozuměj kvůli včasné kontrole)? Kolik procet z již načítaných tříd to je?

    před 4 lety | odpovědět | reagoval [11] David Grudl
  11. David Grudl http://davidgrudl.com #11

    avatar

    #10 juzna.czi, nezkoušel, ale nemyslím, že by byl nějak velký.

    před 4 lety | odpovědět
  12. p4l4cl][n http://gplus.to/tomvolf #12

    avatar

    Idealni by byly dva type hinty… callback a callable.. by resilo veskere problemy

    před 4 lety | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



*kurzíva* **tučné** "odkaz":http://example.com /--php phpkod(); \--