Na navigaci | Klávesové zkratky

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 12 lety
  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 12 lety | reagoval [4] Pitrsonek
  3. Filip Procházka (@HosipLan) #3

    avatar

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

    před 12 lety
  4. Pitrsonek #4

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

    před 12 lety | 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 12 lety
  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 12 lety | reagoval [7] jlk
  7. jlk #7

    avatar

    #6 softice, Javas…wat?

    Ano, je možné psát s diakritikou ☹

    před 12 lety
  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 12 lety | reagoval [9] David Grudl
  9. David Grudl #9

    avatar

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

    před 12 lety
  10. 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 12 lety | reagoval [11] David Grudl
  11. David Grudl #11

    avatar

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

    před 12 lety
  12. p4l4cl][n #12

    avatar

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

    před 12 lety

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


phpFashion © 2004, 2024 David Grudl | o blogu

Ukázky zdrojových kódů smíte používat s uvedením autora a URL tohoto webu bez dalších omezení.