Blíží se Nette 4: základní informace

David Grudl
Nette Core | 7790
+
+39
-

Blíží se vydání nové velké verze Nette 4 a rád bych o ní sepsal pár slov.

(Samozřejmě označení „Nette 4“ je spíš symbolické, protože framework je tvořen sadou nezávislých balíčků, viz Jak se verzuje Nette v době postmonolitické?, a některé mají nižší číslo verze.)

Jak jistě víte a můžete pravidelně číst na blogu, v Nette novinky přicházejí průběžně po celý rok a nečeká se na velké verze. Je to vlastně opačný model, než používá např. PHP, kde novinky přicházejí vždy s velkou verzí jednou ročně.

Velkou verzi tedy vnímám především jako příležitost udělat architektonické úpravy. Například využít nových možností, které přinesl vývoj jazyka PHP. Opravit věci, které šlo navrhnout lépe, nebo se zbavit historických reliktů.

Jak je tomu v případě Nette 4?

PHP 8 typehints

Nette 3 bylo psané na míru PHP 7 a využívalo jeho klíčových novinek. Šlo například o možnost definovat skalární a návratové typy metod. Nová verze Nette 4 je psaná na míru PHP 8.0. A opět to souvisí i s typy, které jsou v osmičce mnohem pokročilejší. Takže Nette 4 je nyní otypované úplně kompletně, i tam kde to v sedmičce ještě nešlo, včetně properties.

Takhle změna může způsobit BC break, pokud dědíte třídu a přepisujete metodu, které byl doplněn typ návratové hodnoty, pak je potřeba jej doplnit i v potomkovi.

PHP 8 named arguments

Opravdu zásadní gamechanger PHP 8 jsou pojmenované argumenty. Jednak legitimizují existenci metod s mnoha parametry, protože místo šíleného

$response->setCookie('lang', $lang, null, null, null, null, null, 'None');

lze psát srozumitelné

$response->setCookie('lang', $lang, sameSite: 'None');

Díky nim také Nette přestane akceptovat zástupné null místo skutečných výchozích hodnot jen kvůli tomu, aby bylo možné snadno „přeskakovat“ parametry jako v předchozím příkladě. Příkladem může být konstruktor Request, kde proto byly parametry $post, $files atd. nullable, ale ve verzi 4 již nebudou.

Pojmenované parametry také daly možnost nahradit tzv. flagy modernějším API. Příkladem může být třeba funkce Strings::match():

Strings::match($s, '~\d+~', PREG_OFFSET_CAPTURE | PREG_UNMATCHED_AS_NULL);

Nevýhoda flagů je, že bez pohledu do dokumentace není zřejmé, které z PREG_* vlastně metoda akceptuje. Také IDE je nemusí napovídat atd. Daleko elegantnější je proto využití pojmenovaných parametrů. Totéž nově v Nette 4:

Strings::match($s, '~\d+~', captureOffset: true, unmatchedAsNull: true);

Přičemž v Nette 4 stále funguje i původní zápis.

SmartObject

Význam třídy Nette\Object a posléze Nette\SmartObject postupně slábne s tím, jak se jazyk PHP vylepšuje. Až se v PHP 8.2 odstraní dynamické properties, už jej nebude pro vylepšení objektového chování PHP potřeba.

Tedy téměř, SmartObject totiž také generuje lepší texty výjimek vylepšené o klauzuli did you mean (což nahradí Tracy) nebo umožňuje snadno vytvářet magic properties. Nette postupně od jejich používání ustupuje a některé (spíše raritní) budou ve verzi 4 označené jako deprecated.

Prefixy rozhraní

Použití prefixů I u rozhraní vidím jako jednu z velkých návrhových chyb, ze které Nette pozvolna a postupně očišťuju (totéž by platilo i pro přípony Interface). V drtivé většině případů to šlo zcela tiše, bez vlivu na zpětnou kompatibilitu. Někdy zase jsem prefix neřešil, protože bylo v plánu přijít z novým rozhraním (například Latte a Tracy). A někdy bylo potřeba změnu rozfázovat do více velkých verzí – tedy i v Nette 4 tento proces pokračuje.

A k jednotlivým knihovnám

  • nette/application přinese zajímavou novinku, které pracovně říkám jednoakční presenter. Budu jí věnovat samostatný thread.
  • Plně se využijí „osmičkové“ atributy. Například pomocí #[Persistent(session: true)] se bude persistentní parametr přenášet v session. Nebo pomocí atributů půjde řídit přístup k action-metodám apod.
  • nette/database není od verze 4 jen obal nad PDO, ale lze jej použít i s PHP rozšířením pro jednotlivé databáze, jako je např. mysqli.
  • A má nové objektové API pro reflexi databázových tabulek a vazeb mezi nimi.
  • nette/http větší abstrakce objektu Response, díky čemuž bude možné řadit request/response objekty do front, kterým se říká middleware.
  • nette/neon má úplně nový AST parser, což využije nette/di k nevídaným featurám
  • Zároveň bude umět načíst soubor .neon, provést změny a uložit jej tak, že se nezmění formátování, neztratí komentáře atd.
  • nette/di: čeká vás řada novinek z hlediska použitelnosti, integrace s Tracy a také podpora všech nových featur PHP 8.
  • nette/finder: sepsal jsem všechny nedostatky, na které jsem během 10 let používání narazil, a vytvořil novou verzi, která je vyřešila.
  • latte: od základu přepsaný parser a kompilátor, díky čemuž bude další vylepšování Latte úplná hračka. Vevnitř to je technicky hodně zajímavé, asi nejlepší kousek co jsem kdy napsal :-), tak o tom někdy povykládám.
  • nette/php-generator: verze 4.0 mění chování funkcí jako addMethod, addClass apod, když přidávaná metoda/třída/apod už existuje. Dříve jí tiše přepsal, teď naopak vyhazuje výjimku
  • nette/schema: nová verze 2.0 odstraňuje mergování s výchozími hodnotami, které bylo pro řadu uživatelů matoucí.
  • tracy: nová verze 3.0 přijde se zcela novým rozhraním pro tvorbu rozšíření. Existující rozšíření budou fungovat nadále.

A kdy to bude?

Postupně jsem začal vypouštět ven testovací verze jednotlivých balíčků. Ostré by měly následovat nejpozději do měsíce. Ale například nette/php-generator už má venku i ostrou verzi.

V případě Latte a DI vycházejí ještě tzv. přechodové verze (Latte 2.11 a DI 3.1), které pomocí notices upozorní na zastaralé věci, které v nových verzích (Latte 3 a DI 4) už nebudou fungovat.

Petr Parolek
Člen | 424
+
-18
-

Ahoj,

koukám, že nic nového nebude v Nette 4… Jen takové drobné vychytávky. Ani jeden náznak z vizí tu https://blog.nette.org/…tich-verzich .

Zkoušel jsem dev master na svém projektu a vše mi naběhlo :) Jen jsem v presenterech musel přepsat zastaralá volání např. $this->session-> na $this->getSession()-> atd.

Editoval Petr Parolek (6. 3. 21:18)

uživatel-p
Člen | 553
+
-10
-

Myslím, že zavedením jednoakčních presenterů se nic nevyřeší. Akorát je to zbytečně vyhozený čas.
Kdo chce dělat presentery jen s jednou akcí to už tak dělá a ten kdo ne, toho to stejně nezastaví.

Viděl jsem už spousty projektů, kde měli borci podle doporučení Presentery s jednou akcí default, ale uvnitř té akce si tahali Request a měli v té akci default switch, který podle URL rozlišoval, co se bude dít a podle toho vybíral šablony, které se mají vykreslit (a v nich samozřejmě komponenty, které tedy na jedné URL neměly co dělat, ale stejně šly zavolat.).

Podle mě je tedy jednoakční Presenter zbytečná práce, která nicneřeší a bezmyšlenkovité plýtvání zdroji, které mohly být použity na vývoj něčeho smysluplného.

Kamil Valenta
Člen | 577
+
+8
-

Polki napsal(a):

Myslím, že zavedením jednoakčních presenterů se nic nevyřeší.

Pokud by to byl jen presenter s akcí default, tak bych i souhlasil. Pokud tomu ale má být věnovaný samostatný thread, tak bude myšlenka patrně širší a pak je brzy na nějaké soudy, ne?

uživatel-p
Člen | 553
+
0
-

@KamilValenta Máš pravdu. Možná to nebude jen jednoakční presenter, ale pod tím názvem se bude skrývat ještě něco dalšího. Uvidíme, co přinese ten thread.

srigi
Nette Blogger | 555
+
0
-

Mne sa velmi pacia jednoakcne Controllery v Symfony s metodou “__invoke()”: https://symfony.com/…service.html#…. Tusim maju aj nejaky DI sugar, ze sa DI sluzby predavaju do akcie rovno ako argumenty.
Ak toto pride teraz do Nette, tak odpovedam “pecka” a “konecne”

bazo
Člen | 620
+
+2
-

srigi napsal(a):

Mne sa velmi pacia jednoakcne Controllery v Symfony s metodou „__invoke()“: https://symfony.com/…service.html#…. Tusim maju aj nejaky DI sugar, ze sa DI sluzby predavaju do akcie rovno ako argumenty.
Ak toto pride teraz do Nette, tak odpovedam “pecka” a “konecne”

len to nie. tie sluzby ako argumenty maju aj normalne controllery, potom tam ludia prasia kadeco

Marek Bartoš
Nette Blogger | 747
+
+1
-

DI sluzby predavaju do akcie rovno ako argumenty

S tímhle by vyvstal problém, zda jde o parametr z routeru nebo z DI. Z obou může legitimně přijít string, z obou teoreticky může přijít i služba.