nette/application 3.3 is coming soon, please help test it

David Grudl
founder | 8315
+
+1
-

I'd like to ask you to test nette/application 3.3.0-RC. Before I release it as stable, I'd like to make sure the upgrade goes smoothly. The version brings modernized requirements, more reliable CSRF protection, a few minor BC breaks, and deprecates a number of very outdated constructs.

Requires PHP 8.3.

More reliable CSRF protection

Protection now verifies that a request came from the same origin using the browser's Sec-Fetch-Site header, which the browser sends itself, instead of the previous reliance on a custom SameSite cookie. It is therefore stateless (no cookie needed) and works reliably even in browsers where SameSite cookies were unreliable. On top of that, it checks the match of the whole origin (scheme, domain and port), which is stricter than the previous same-site that also tolerated subdomains. For background, see the blog article.

This applies to automatically protected signals in forms as well as the #[Requires(sameOrigin: true)] attribute. The only practical impact: directly opening a signal link (a bookmark, a link in an e-mail) no longer counts as same-origin. If you need to allow it somewhere, use #[Requires(sameOrigin: false)].

Other new features

  • Default mapping is now App\Presentation\*\**Presenter (instead of the ancient *Module\*Presenter). Anyone who has mapping configured explicitly (i.e. everyone) is unaffected. Finally, with no configuration it matches the default structure described throughout the documentation, e.g. app/Presentation/Home/HomePresenter.php.
  • URL fragment via the # key in arguments: link('Product:detail', ['#' => 'reviews']) produces the fragment ...#reviews. The value is encoded.
  • Presenter::completeTemplate() – a new protected method extracted from sendTemplate(). You can override it to add shared variables to the template or set the file.

@annotations are replaced by attributes

It's time to say goodbye to @annotations; this version warns you with a deprecation notice that you should replace them with attributes:

  • @persistent#[Nette\Application\Attributes\Persistent]
  • @crossOrigin#[Nette\Application\Attributes\Requires(sameOrigin: false)]
  • @deprecated#[Nette\Application\Attributes\Deprecated]

Application::processRequest() returns Response

The method no longer sends the response itself, but returns it. Sending is handled by run(). The motivation is easier use in long-running environments (RoadRunner, FrankenPHP), PSR integration, and the ability to extend Application without copying code (see issue #348). If you call processRequest() manually, you need to send the returned response yourself:

$response = $application->processRequest($request);
$response->send($httpRequest, $httpResponse);

LatteFactory::create() takes ?Control

This is a BC break in the LatteFactory interface. The signature is now create(?Control $control = null). It affects anyone who has a custom implementation of LatteFactory.

Deprecating old oddities

The ancient way of building a router with array access:

$router[] = new Route('...');   // deprecated
$router->addRoute('...');       // correct
  • a query string in a link destination, e.g. n:href="Product:detail?x=1&y=2". The correct way is to pass arguments as: n:href="Product:detail, x: 1, y: 2".
  • access to some magic properties ($presenter->view, $layout, $request, $session…) is marked as deprecated in favor of getters.
  • removed the second $default parameter of Component::getParameter()
  • removed the {ifCurrent} tag – use {if isLinkCurrent('...')}.
  • removed support for Latte 2 (requires Latte 3.1)
  • removed compatibility with old class names (PresenterComponent, IRouter, etc.).

Thanks in advance for testing and for your feedback.