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í potomkemPDO
- přejmenujte metody
exec()
→query()
,fetchColumn()
→fetchField()
alastInsertId()
→getInsertId()
Nette\Database\Statement
je nyníNette\Database\ResultSet
a též už není potomkemPDOStatement
- přejmenujte metody
rowCount()
→getRowCount()
acolumnCount()
→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 zConnection
do nové třídyNette\Database\Context
. Ta obsahuje obsahuje všechny důležité metody pro práci s databází, takže klidně změňteConnection
zaContext
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 metoduhaving()
(Pokud jste používali SelectionFactory
v dev-verzi, změňte
ji také na Context
.)
Dependency Injection (DI)
- třída
Nette\Config\Configurator
→Nette\Configurator
(původní název zněl, jako když se člověk zakoktá) - v konfiguračním souboru se sloučily definice
factories
aservices
do společnéhoservices
. 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()
acreateBasicForm()
- a ke službám přistupujte raději přes
$container->getService()
čigetByType()
namísto$container->nazevSluzby
Pokud píšete vlastní rozšíření, vězte, že došlo k přejmenování
jmenných prostorů Nette\Config
→ Nette\DI
a
Nette\Utils\PhpGenerator
→ Nette\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žijtegetContext()->getService()
), dálegetHttpContext()
agetApplication()
- magické
getParameter(null)
→getParameters()
- místo divného
invalidateControl()
lze používatredrawControl()
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í nan:name
, aby šel použít nejen na<input>
, ale i label, select, form a textarea - zavržená jsou makra
{attr}
(nahrazujen: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
aFLOAT
převádí hodnotu na integer resp. float - TextArea: zrušeny výchozí hodnoty atributů
cols
arows
(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::$blueScreen
→Debugger::getBlueScreen()
- a adekvátně
$bar
→getBar()
,$logger
→getLogger()
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()
ahtmlDump()
, které nahrazuje nová třídaDumper
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()
amb_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říduNette\Callback
, neboť globální funkce mohou způsobit komplikace - přejmenoval se jmenný prostor
Nette\Utils\PhpGenerator
→Nette\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
Honza Marek #1
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 ;)
David Grudl #2
#1 Honzo Marku, to máš jako v JavaScriptu
var abc = 123
nebo dříve v PHPvar $abc = 123;
, tak i v Latte je{var $abc = 123}
.Honza Marek #3
#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.
Roman Mátyus #4
Vďaka za Nette 2.1 a fajn zhrnutie. Super Vianočný darček;)
enumag #5
„zavržené jsou metody getService() (použijte getContext()->getService())“
tohle je divný, afaik getContext je zavržený taky: https://github.com/…resenter.php#…
David Grudl #6
#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.uestla #7
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.
Martinit #8
#7 uestlo, Řekl by, že to bude souviset s commitem https://github.com/…5e9bd2083413
Michal #9
#7 uestlo, Myslím že stále existuje. Jen je v Nette\Utils\Callback
Edit: Pozdě 🙂
Jakub Vrána #10
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ě.David Grudl #11
#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řídaNette\Callback
s novými verzemi PHP pomalu ztrácí význam a jde nahradit statickouNette\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.
Jakub Vrána #12
#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.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?
David Grudl #14
#13 Lukáši,
$row->date->format()
můžeš používat.sKopheK #15
„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“ :)
David #16
#15 sKophKu, to dělá až ve vývojové verzi 2.2
Adam #17
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 ?
Pavel #18
čí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ď.
justpassingby #19
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‘].
Olda #20
„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ří :).
Tento článek byl uzavřen. Už není možné k němu přidávat komentáře.