Přechod na verzi 2.1

Nová verze přináší nové vlastnosti a některé nekompatibility, které je třeba projít a kód otestovat před nasazením nové verze.

Nové vlastnosti

Application & Presenter

  • Presenter: new method sendJson()
  • PresenterFactory: configurable mapping Presenter name → Class name
  • Route: new pseudo-variables %basePath%, %tld% and %domain%

Caching

  • added SQLite storage (Nette/Caching/Storages/SQLiteStorage)

Database (NDB)

  • complete refactoring, a ton of bug fixes
  • Connection:
    • lazy connection
    • all queries are logged (error queries, transactions, …)
    • added onConnect event
    • DSN in connection panel
  • much better (dibi-like) SQL preprocessor
  • Selection, ActiveRow: insert() & update() methods return row instances with refetched data
  • Selection: added placeholder support select(), group(), having(), order() methods
  • SqlLiteral: added placeholder support
  • Selection:
    • added: WHERE conditions consider NOT for IN operator
    • insert() method returns IRow
  • drivers:
    • new driver for Sqlsrv
    • Sqlite supports multi-inserts
    • fixes for PostgreSQL

Debugger

  • Dumper: colored and clickable dumps in HTML or terminal
  • Debugger: full stack trace on fatal errors (requires Xdebug)
  • Debugger: method barDump() accepts options
  • BlueScreen: new property $collapsePaths which allows you to configure which paths are collapses in stack trace
  • Bar: you can see bar after redirect
  • Bar: new method getPanel()
  • Dumper: possibility to include JS & CSS separately

Dependency Injection (DI)

  • annotation @inject
  • auto-generated factories and accessors via interface
  • adding compiler extensions via config file
  • auto-detection of sections in config file
  • configurable presenters via config file
  • Container: new methods findByType() and callInjects()
  • bullet syntax for anonymous services

Forms

  • setOmitted: excludes value from $form->getValues() result
  • implemented full validation scopes
  • data-nette-rules attribute is JSON
  • Form::getOwnErrors() returns only errors attached to form
  • Radiolist::getLabel(…, $key) returns label for single item
  • added ChoiceControl, MultiChoiceControl and CheckboxList
  • SelectBox and CheckboxList: allowes to disable single items
  • UploadControl allowes multiple files upload
  • validators Form::INTEGER, NUMERIC and FLOAT converts values to integer or float
  • validator Form::URL prepends http:// to value
  • Form::getHttpData($htmlName) returns data for single field
  • supports Twitter Bootstrap 2 & 3 (see examples)
  • removed dependency on Environment
  • improved toggles
  • improved netteForms.js

Latte

  • supports <tag attr=$val> without quotes
  • new macro n:name for <form> <input> <select> <textarea>
  • partially rendered radiolists using {input name:$key} and {label name:$key}
  • new modifier |safeurl which allowes only http(s), ftp and mailto protocols
  • safeurl is automatically used for href, src, action and formaction attributes (can be bypassed by |nosafeurl modifier)
  • new modifier |noescape which is preferred over exclamation mark
  • {foreach ...|nointerator} bypasses creating variable $iterator
  • new macro n:ifcontent
  • {include block} can be written without hash
  • template allows helpers overriding
  • native support for empty macros {macro /}
  • a lot of small improvements
  • PhpWriter supports indexed arguments like %1.raw

Http

  • added new SessionPanel
  • Helpers: new method ipMatch()
  • RequestFactory: new method setProxy()
  • Url: new methods getQueryParameter() and setQueryParameter()

Utils

  • Arrays: new method isList()
  • Arrays: method flatten() supports key preserving
  • Strings: new methods findPrefix() and normalizeNewLines()
  • Json: supports pretty output
  • Neon: is superset of JSON
  • Validators: new method isType()
  • new utility class FileSystem
  • new utility class Callback

Mailing

  • SmtpMailer: persistent connection
  • SmtpMailer: some methods protected and can be overloaded

Others

  • minified version is PHAR file
  • ObjectMixin: new methods getMagicMethods, getExtensionMethod, setExtensionMethod and checkType
  • ObjectMixin: magic methods setProperty(), getProperty(), isProperty() and addProperty() by @method
  • both RobotLoader and NetteLoader can be registered before existing autoloaders instead of after
  • SafeStream: supports ftruncate (requires PHP 5.4+)

Nekompatibility

Database (NDB)

  • 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()
  • MySQL: removed timezone setting. Use onConnect[] event instead. (commit)

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 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()
  • Selection: removed support for INNER join in where statement (commit)

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

Dependency Injection (DI)

  • třída Nette\Config\ConfiguratorNette\Configurator
  • 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árny jako createLatte(), createCache(), createMail()createBasicForm()
  • a ke službám přistupujte raději přes $container->getService() či getByType() namísto $container->nazevSluzby
  • Container: removed property $classes, removed parameter $meta in method addService()
  • ServiceDefinition: removed property $internal and method setInternal()
  • ContainerBuilder: method generateClass() is deprecated, use generateClasses()[0] instead
  • ContainerBuilder operates on expanded parameters, removed Helpers: escape()
  • Configurator: deprecated parameter productionMode, use debugMode instead
  • Configurator: methods setProductionMode, isProductionMode and detectProductionMode are deprecated, use *Debug* variants instead
  • Container: removed deprecated property $params, use $parameters instead

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.

Application & Presenter

  • 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()
  • Application: methods storeRequest() and restoreRequest() are deprecated, call them on UI\Presenter instead
  • Application\Routers\Route: foo-parameters are not optional when pattern is missing

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ý
  • native support for empty macros, use for example {label foo /} instead of {label foo}

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

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
  • Form: removed deprecated event $onInvalidSubmit, use $onError instead
  • RadioList: calling getValue(true) is deprecated, use getRawValue() instead

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.
  • Mail\Message: methods setHtmlBody() and setBody() render template immediately
  • MimePart: removed method generateMessage(), use getEncodedMessage() instead

ostatní

  • Nette Framework opouští PHP 5.2, s přechodem na jmenné prostory vám pomůže nástroj migration-53.php
  • 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\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\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í.
  • InstanceFilter: removed entirely
  • ResursiveFilter: removed method accept() and parameter $childrenCallback in constructor
  • RequestFactory: removed method setEncoding(), only UTF-8 and binary (via setBinary()) is now supported
  • ObjectMixin: removed method callProperty()
  • ObjectMixin: removes support for non-registered extension methods (*_prototype_* functions)