Na navigaci | Klávesové zkratky

Translate to English… Ins Deutsche übersetzen…

Přejděte na Nette 2.1

Před chvílí vyšel Nette Framework 2.1. Ačkoliv číselně jde o desetinkový posun, novinek je hromada. K těm se překvapivě dostanu až v příštích článcích, nyní mi půjde o kompatibilitu.

Na tu vždycky Nette Framework velmi dbal:

  • nikdy mezi verzemi nebyla tlustá čára, vývoj je evoluční
  • ačkoliv je psán v PHP 5.3, generovala se i verze pro PHP 5.2
  • s přechodem na jmenné prostory dostali vývojáři nástroj, jenž jim všechny třídy ve zdrojových kódech přejmenoval

Přechod na verzi 2.1 by měl být snadný. Teď si říkáte: „kilometr dlouhý článek a snadný přechod?“ Inu, snaží se být vyčerpávající. Mám weby, na kterých nebylo potřeba měnit nic.

Byť se pár věcí přejmenovalo, v případě tříd existují aliasy a fungují i staré názvy metod, jen se vypíše či zaloguje upozornění. Nicméně kvůli technikáliím doporučuji stejně těch pár tříd přejmenovat, máte k tomu i nástroj na automatické přejmenování tříd.

Zamáčkněte slzu, Nette Framework 2.1 opouští PHP 5.2, verzi, kterou už 3 roky nepodporuje ani samotné PHP. Minimální požadovaná verze je tak 5.3.1 a Nette by mělo jet prakticky na každém pětrojkovém hostingu (je testováno i na nejnovější 5.5.7).

Minimalizovaná verze se nyní generuje ve formátu PHAR, takže v distribuci místo nette.min.php najdete soubor nette.phar, se kterým se však pracuje úplně stejně.

Nette Database (NDB)

NDB společně s Dependency Injection byly čerstvé části frameworku a bylo zřejmé, že nejvíce změn bude právě tady.

  • Nette\Database\Connection již není potomkem PDO
  • přejmenujte metody exec()query(), fetchColumn()fetchField() a lastInsertId() → getInsertId()
  • Nette\Database\Statement je nyní Nette\Database\ResultSet a též už není potomkem PDOStatement
  • přejmenujte metody rowCount()getRowCount() a columnCount() → getColumnCount()

Používáte Nette Database Table (NDBT), tedy skvělou část NDB, ke které se přistupuje přes $database->table(...)?

  • metoda table() byl přesunuta z Connection do nové třídy Nette\Database\Context. Ta obsahuje obsahuje všechny důležité metody pro práci s databází, takže klidně změňte Connection za Context a máte hotovo.
  • proměnné řádku ActiveRow jsou nyní read-only, pro změnu slouží metoda $row->update(array('field' => 'value')). Věřte, že dřívější chování mělo tolik úskalí, že jiná cesta nebyla.
  • změnila se tzv. backjoin syntaxe z book_tag:tag.name na :book_tag.tag.name (dvojtečka na začátku)
  • místo druhého parametru $having v metodě group() použijte metodu having()

(Pokud jste používali SelectionFactory v dev-verzi, změňte ji také na Context.)

Dependency Injection (DI)

  • třída Nette\Config\ConfiguratorNette\Configurator (původní název zněl, jako když se člověk zakoktá)
  • v konfiguračním souboru se sloučily definice factories a services do společného services. Jen těm, co byly původně factories, přidejte klíč autowired: no.
  • a zavedl se „odrážkový“ zápis anonymních služeb:
services:
    Jmeno\Tridy: self  # dříve, ukázalo se jako matoucí

    - Jmeno\Tridy  # nyní

Pracovat přímo s DI kontejnerem není obvykle dobrý nápad, ale pokud už tak činíte:

  • tovární metody volejte jako $container->createService('nazevsluzby') namísto $container->createNazevSluzby()
  • zavrženy jsou všechny výchozí továrničky jako createLatte(), createCache(), createMail()createBasicForm()
  • a ke službám přistupujte raději přes $container->getService() či getByType() namísto $container->nazevSluzby

Pokud píšete vlastní rozšíření, vězte, že došlo k přejmenování jmenných prostorů Nette\ConfigNette\DI a Nette\Utils\PhpGeneratorNette\PhpGenerator.

Oproti dev-verzi jsou anotace @inject a metody inject() automaticky zpracovány jen na presenterech. Na jiných službách je zapnete uvedením klíče inject: yes v definici.

Používáte-li ještě stařičký Environment, bude po vás vyžadovat nastavenou konstantu TEMP_DIR, kvůli výkonu.

Ufff, máme za sebou tu náročnou část. Teď už to bude brnkačka.

UI\Presenter a Control

  • Presenter nyní zabraňuje, aby vám někdo podstrčil do persistentního parametru pole. Pokud ale pole chcete, uveďte ho jako výchozí hodnotu,
  • zavržené jsou metody getService() (použijte getContext()->getService()), dále getHttpContext()getApplication()
  • magické getParameter(NULL)getParameters()
  • místo divného invalidateControl() lze používat redrawControl()

Tak to je easy, ne? Pojďme si dát Latte.

Latte

  • výchozím režimem je HTML (namísto XHTML), což lze přepnout v konfiguraci
  • automaticky ouvozovkuje atributy v <a title={$title}>, což by nemělo způsobit žádnou komplikaci, ale raději to zmiňuji
  • atribut n:input se mění na n:name, aby šel použít nejen na <input>, ale i label, select, form a textarea
  • zavržená jsou makra {attr} (nahrazuje n:attr) a {assign} → {var}
  • doporučujeme místo vykřičníkového zápisu {!$var} přejít na {$var|noescape}, je to zřejmější
  • pokud jste v dev-verzi používali zkrácený zápis bloků {#block}, tak do 2.1 se nedostal, nebyl srozumitelný

V Latte je novinka, která v <a href={$url}> automaticky kontroluje, zda proměnná $url neobsahuje něco jako javascript:hackniWeb(). Povolené jsou pouze protokoly http, https, ftp, mailto a pochopitelně relativní cesty a kontroluje i atributy src, action, formaction a také <object data=...>. Pokud někde potřebujete vypsat URL bez kontroly, použijte modifikátor |nosafeurl.

A nakonec: drobná změna souvisí s ručním vykreslování checkboxů, ale o tom níže.

Formuláře

Přes obrovskou spoustu novinek ve formulářích je možných nekompatibilit málo.

Checkboxy a RadioListy se nyní vykreslují v praktičtějším tvaru <label><input>...</label> namísto <label>...</label><input>. Jako důsledek u Checkbox metoda getLabel() či {label} nevrací nic a getControl() či {input} HTML v onom novém tvaru. Pokud ale potřebujete staré chování, přepněte se do tzv. partial renderingu přidáním dvojtečky: {label nazevprvku:} a {input nazevprvku:}. Easy.

Makro {control form} nyní vždy vypisuje chybové zprávy u jednotlivých prvků a nad formulářem jsou jen ty nepřiřazené. Doporučujeme to tak dělat i při manuálním vykreslování, třeba takto.

  • setValue() u prvků kontroluje hodnotu a v případě chyby vyhodí výjimku namísto dřívějšího mlčení
  • validační pravidla jako Form::INTEGER, NUMERIC a FLOAT převádí hodnotu na integer resp. float
  • TextArea: zrušeny výchozí hodnoty atributů cols a rows (existovaly jen proto, že to HTML4 vyžadovalo)
  • prvky označené setDisabled() se neobjeví ve $form->getValues() (prohlížeč je totiž vůbec neposílá)
  • zavrženo SelectBox::setPrompt(TRUE), místo TRUE použijte řetězec
  • přejmenováno MultiSelectBox::getSelectedItem()getSelectedItems()
  • v HTML atributech data-nette-rules se používá JSON, takže nezapomeňte nasadit aktuální netteForms.js

Debugger

  • Nette\Diagnostics\Debugger::$blueScreenDebugger::getBlueScreen()
  • a adekvátně $bargetBar(), $loggergetLogger() a $fireLogger → getFireLogger()
  • zavrženo Nette\Diagnostics\Debugger::tryError(), catchError() a také toStringException(), místo kterého použijte obyčený trigger_error()
  • zavrženy interní Nette\Diagnostics\Helpers::clickableDump() a htmlDump(), které nahrazuje nová třída Dumper

Mail

Zavržená metoda Nette\Mail\Message::send(), použijte mailer, viz dokumentace.

ostatní

  • Nette nemusí fungovat s eAccelerator a minifikovaný PHAR nemusí fungovat s APC
  • Nette\Utils\Finder::find($mask) filtruje podle masky nejen soubory, ale i adresáře
  • do Nette\Security\User se v konstruktoru předává autentikátor, pozor na kruhové závislosti
  • v loaderu se už nenastavuje iconv_set_encoding() a mb_internal_encoding()
  • zavrženy konstanty NETTE, NETTE_DIR a NETTE_VERSION_ID
  • a třída Nette\Loaders\AutoLoader
  • a proměnná Nette\Framework::$iAmUsingBadHost
  • doporučujeme přestat používat callback() a třídu Nette\Callback, neboť globální funkce mohou způsobit komplikace
  • přejmenoval se jmenný prostor Nette\Utils\PhpGeneratorNette\PhpGenerator
  • Nette varuje hláškou „Possible problem: you are sending a cookie while already having some data in output buffer,“ pokud se snažíte odeslat HTTP hlavičku nebo cookie a byl již odeslán nějaký výstup – byť do bufferu. Buffer totiž může přetéct a proto to varování.

Vyzkoušejte!

Stáhněte si verzi 2.1 a vyzkoušejte ji! A těšte se na články o novinkách :-)

Komentáře

  1. Honza Marek http://www.janmarek.net #1

    avatar

    Já bych {assign} ani {var} nezavrhával, protože si sice pamatuju, že existujou obě verze, ale nemám tušení, která je ta „správná“. Myslim, že z těch dvou slov nějaká lepší varianta vůbec nejde poznat a sám je asi používám na střídačku ;)

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

    avatar

    #1 Honzo Marku, to máš jako v JavaScriptu var abc = 123 nebo dříve v PHP var $abc = 123;, tak i v Latte je {var $abc = 123}.

    před 3 lety | odpovědět | reagoval [3] Honza Marek
  3. Honza Marek http://www.janmarek.net #3

    avatar

    #2 Davide Grudle, No jo, ale var je deklarace, volitelně s přiřazením defaultní hodnoty. Funkce toho makra je přiřazení, tedy assign.

    před 3 lety | odpovědět
  4. Roman Mátyus http://romiix.org #4

    avatar

    Vďaka za Nette 2.1 a fajn zhrnutie. Super Vianočný darček;)

    před 3 lety | odpovědět | reagoval [6] David Grudl
  5. enumag #5

    avatar

    „zavržené jsou metody getService() (použijte getContext()->getService())“
    tohle je divný, afaik getContext je zavržený taky: https://github.com/…resenter.php#…

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

    avatar

    #4 Romane Mátyusi, díky!

    #5 enumagu, dalo by se říct „slabě zavržený“, protože funguje bez jakéhokoliv omezení. Tedy zatím. Ideální je samozřejmě kontejner nepoužívat a předávat si přímo služby či továrničky přes konstruktor. Druhá možnost je předat si konstruktorem i samotný kontejner a netřeba se na getContext() spoléhat.

    před 3 lety | odpovědět
  7. uestla #7

    avatar

    Přidávám se k díkům za pěkné shrnutí i za nové Nette jako takové.

    Mám jen dotaz k zavržení Nette\Callback – byla to taková pěkná schránka zabalující všechny různé možnosti, jakými v PHP callback vytvořit, a často ji používám. Proč byl zavržen?

    Děkuju.

  8. Martinit #8

    avatar

    #7 uestlo, Řekl by, že to bude souviset s commitem https://github.com/…5e9bd2083413

    před 3 lety | odpovědět
  9. Michal #9

    #7 uestlo, Myslím že stále existuje. Jen je v Nette\Utils\Callback

    Edit: Pozdě :-)

    před 3 lety | odpovědět
  10. Jakub Vrána http://www.vrana.cz #10

    avatar

    Zmínka o přesunu PhpGenerator je v článku dvakrát.

    Nezvažoval jsi podporu Latte syntaxe var a = '{$a}'? Funguje s tím líp zvýrazňování syntaxe v editorech a někdy to je i přirozenější. Na zařazení do 2.1 už by ale stejně asi bylo pozdě.

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

    avatar

    #7 uestlo, funkci callback samotný framework nepoužívá a jelikož její existence může způsobit problém, bylo by vhodné ji přesunout z frameworku do samotné aplikace. Třída Nette\Callback s novými verzemi PHP pomalu ztrácí význam a jde nahradit statickou Nette\Utils\Callback

    #10 Jakube Vráno, znamenalo by to udělat parser Javascriptu, což by nemuselo být úplně snadné. Ale je fakt, že pokud je před nebo za proměnnou uvozovka, je to zcela jistě chybné použití, které by mohlo generovat výjimku.

    před 3 lety | odpovědět | reagoval [12] Jakub Vrána
  12. Jakub Vrána http://www.vrana.cz #12

    avatar

    #11 Davide Grudle, Aha, myslel jsem, že už tam parser JS je. Ale on vlastně být nemusí, protože konec JavaScriptu se pozná snadno podle </script> nezávisle na kontextu.

    před 3 lety | odpovědět
  13. Lukáš #13

    Teď se tedy nebude dát používat $row->date->format(), když je ActiveRow jenom pro čtení. Jak tedy můžu zformátovat objekt DateTime, který tahám z databáze, aniž bych musel používat formát již při dotazu?

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

    avatar

    #13 Lukáši, $row->date->format() můžeš používat.

    před 3 lety | odpovědět
  15. sKopheK #15

    avatar

    „doporučujeme místo vykřičníkového zápisu {!$var} přejít na {$var|noescape}“
    Ona to je spíš nutnost, když to jinak háže chybu „User Deprecated: The noescape shortcut {!…} is deprecated, use {…|noescape} modifier“ :)

    před 3 lety | odpovědět | reagoval [16] David
  16. David #16

    avatar

    #15 sKophKu, to dělá až ve vývojové verzi 2.2

    před 3 lety | odpovědět
  17. Adam #17

    avatar

    Prosím nemohli by ste prerobiť dokumentáciu ? Aspoň trošku nech sa z nej niečo naučí aj začiatočník ? Je tam kopa nezrozumiteľných vecí, priveľa vysvetľovania ale slabé príklady, ako napríklad v Komponenty → Signál neboli subrequest je tam príklad na handleClick v komponente ale nikde neni odkiaľ sa na ten handleClick dostaneme či z nejakeho view alebo odkiaľ ho naplníme …

    Prosím spravte s tým niečo, alebo napíšte nejaký serial ako sa naučiť aktualizovanú verziu Nette, všade je len všetko staré. Niekde som čítal že prudká krivka učenia, snažím sa fakt naučiť sa ho čo najlepšie, je síce v češtine čo je super, ale príde mi že sa anglický framework(napríklad Yii) dokážem naučiť omnoho rýchlejšie. Keďže všade po nete sú nejaké príklady ako čo spraviť, viem že príklady sú aj na github ale čo z toho má začiatočník ako ja keď nette nepoznám a mám to tam hľadať čo, ako, kde sa prepája a ako to funguje keď tam neni žiaden postup ?

    před 3 lety | odpovědět
  18. Pavel #18

    avatar

    čím mám nahradiť \Nette\Environment::getConfig(„data“) vo verzii 2.1?

    Mám použit DI (dependency injection)?
    Ako na to v prípade, keď chcem získať parametre v parent classe?
    Ďakujem za odpoveď.

    před 3 lety | odpovědět
  19. justpassingby #19

    avatar

    Jen poznámka: všiml jsem si, že $this->context->params je teď $this->context->parameters.

    Třeba stav produkčního režimu: $this->context->parameters[‚productionMode‘].

    před 3 lety | odpovědět
  20. Olda #20

    avatar

    „proměnné řádku ActiveRow jsou nyní read-only, pro změnu slouží metoda $row->update(array(‚field‘ ⇒ ‚value‘)). Věřte, že dřívější chování mělo tolik úskalí, že jiná cesta nebyla.“

    Škoda. U obsahů článků při ukládání odebírám adresy souborů (z daného webu) a při zobrazování je zase přidávám. (Nejsem potom závislý na adrese webu. Mohu změnit adresu webu a odkazy na soubory stále fungují.) Jednoduše jsem si článek při vytahování z db projel nějakým filtrem a potom zase vrátil do proměnné v ActiveRow. Šablona nic nepoznala. No svět se nezboří :).

    před 3 lety | odpovědět

Zanechat komentář

Text komentáře
Kontakt

(kvůli gravataru)



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