nette/application
Nette Application is a lightweight MVC layer for PHP web apps, offering presenters, flexible routing, HTTP request/response handling, and reusable UI components. It integrates smoothly with Nette Framework and supports clean, testable application structure.
A hardening release. Crafted or malformed request parameters that used to slip through as uncaught 500s now degrade gracefully to 4xx. If your site gets probed by scanners – and it does – these three fixes turn a batch of "Server Error" reports into clean Bad Request / Not Found responses.
redirect('this'), forward('this'), isLinkCurrent('this'), typically from a language switcher) while the current URL carries a parameter that doesn't fit the action's typed signature (e.g. ?id=abc for int $id), the framework raised an uncaught InvalidLinkException (HTTP 500). It now reports a proper BadRequestException (4xx) through the new InvalidRequestParameterException. Explicitly passed bad link arguments still throw InvalidLinkException, so genuine programmer mistakes stay visible.?1-foo=bar produced a numeric component id that hit getComponent()'s string type hint and threw a TypeError (HTTP 500). The id is now cast to string and the request is handled gracefully.?do[]=x could crash Tracy's routing panel during development. It now skips non-string presenter/signal/action values instead of throwing.Nette Application 3.3 modernizes the foundations: PHP 8.3+ and Latte 3.1, more reliable CSRF protection driven by the browser itself, and a default presenter mapping that finally matches the structure used throughout the documentation. It also clears out a pile of long-forgotten legacy. Please test the RC and report anything that breaks before the stable release.
Sec-Fetch-Site header instead of a SameSite cookie.App\Presentation\*\**PresenterApplication::processRequest() returns a Response instead of sending it itself (#350) – sending is handled by run(). This enables long-running runtimes (RoadRunner, FrankenPHP) and PSR integration.Presenter::getRequest() throws instead of returning null when the presenter isn't running yetLatteFactory::create() now takes ?Control – update any custom LatteFactory implementation to the new create(?Control $control = null) signature.{ifCurrent} – use {if isLinkCurrent('...')}.PresenterComponent and IRouter.Mostly very old curiosities that few people knew existed – they still work but now emit a deprecation notice:
[@annotations](https://github.com/annotations) → PHP attributes: [@persistent](https://github.com/persistent) → #[Persistent], [@crossOrigin](https://github.com/crossOrigin) → #[Requires(sameOrigin: false)], [@deprecated](https://github.com/deprecated) → #[Deprecated].RouteList – $router[] = new Route(...) and friends are replaced by $router->addRoute(...) / getRouters().link('Product:detail?id=1') should pass arguments instead: link('Product:detail', ['id' => 1]).Component::getParameter() second $default argument – use the ?? operator instead.$presenter->view, $layout, $request, $session…) – use the getters.link('Product:detail', ['#' => 'reviews']) produces ...#reviews. The value is URL-encoded, must be scalar, and isn't passed on as a request parameter.Presenter::completeTemplate() – a protected method extracted from sendTemplate() that you can override to inject shared variables or set the template file before rendering.Nette Application 3.3 modernizes the foundations: PHP 8.3+ and Latte 3.1, more reliable CSRF protection driven by the browser itself, and a default presenter mapping that finally matches the structure used throughout the documentation. It also clears out a pile of long-forgotten legacy. Please test the RC and report anything that breaks before the stable release.
Sec-Fetch-Site header instead of a SameSite cookie.App\Presentation\*\**PresenterApplication::processRequest() returns a Response instead of sending it itself (#350) – sending is handled by run(). This enables long-running runtimes (RoadRunner, FrankenPHP) and PSR integration.Presenter::getRequest() throws instead of returning null when the presenter isn't running yetLatteFactory::create() now takes ?Control – update any custom LatteFactory implementation to the new create(?Control $control = null) signature.{ifCurrent} – use {if isLinkCurrent('...')}.PresenterComponent and IRouter.Mostly very old curiosities that few people knew existed – they still work but now emit a deprecation notice:
[@annotations](https://github.com/annotations) → PHP attributes: [@persistent](https://github.com/persistent) → #[Persistent], [@crossOrigin](https://github.com/crossOrigin) → #[Requires(sameOrigin: false)], [@deprecated](https://github.com/deprecated) → #[Deprecated].RouteList – $router[] = new Route(...) and friends are replaced by $router->addRoute(...) / getRouters().link('Product:detail?id=1') should pass arguments instead: link('Product:detail', ['id' => 1]).Component::getParameter() second $default argument – use the ?? operator instead.$presenter->view, $layout, $request, $session…) – use the getters.link('Product:detail', ['#' => 'reviews']) produces ...#reviews. The value is URL-encoded, must be scalar, and isn't passed on as a request parameter.Presenter::completeTemplate() – a protected method extracted from sendTemplate() that you can override to inject shared variables or set the template file before rendering.hasPresenter()/getPresenterIfExists() addition and the $throw deprecation in Component/Form::getPresenter() – the previous API behavior stays unchangedApplication, FileResponse, JsonResponse, RedirectResponse, TextResponse, ForwardResponse and CliRouterPresenterFactory, CallbackResponse and Multiplier are normalized to Closure for stronger typing|absoluteUrl and {linkBase}Component::tryCall() throws BadRequestExceptionMultiplier::createComponent() allow to return a null (#327)changes:
Presenter::createTemplate() has argumentComponent::tryCall() throws BadRequestException#[Requires] and #[Deprecated]switch()**ComponentReflection::getActionRenderMethod() & getSignalMethod()LatteFactory::create()ComponentReflection::convertType() supports true & falsePresenter::findLayoutTemplateFile()<script>detectedCsrf() #300Control::templatePrepareFilters() silently deprecatedComponent::getParameter() $default is silently deprecatedwithPath() fix II.Component::link() & etc uses variadic parameter" #298Presenter::run() saves global state on sendRequest()Presenter::canonicalize() uses variadicsComponent::link() & etc uses variadic parameter{control |noescape}formatTemplateClass() refactoringcreateRequest() #262Form::disableSameSiteProtection() replaced with allowCrossOrigin()disableSameSiteProtection() replaced with allowCrossOrigin()For the details you can have a look at the diff.
createComponent() warns on non-presenter components nette/forms#147createTemplate() returns Nette\Bridges\ApplicationLatte (BC break)For the details you can have a look at the diff.
{control x: 1}For the details you can have a look at the diff.
#[Persistent] & [CrossOrigin]#For the details you can have a look at the diff.
getModule() #264withReferenceUrl()For the details you can have a look at the diff.
For the details you can have a look at the diff.
For the details you can have a look at the diff.
restoreRequest() redirects on GET requestisLinkCurrent() and isModuleCurrent()isModuleCurrent() #240 (#243)For the details you can have a look at the diff.
addFunction() for Latte 2.6injectPrimary() params are required because $httpRequest is required. (#239)For the details you can have a look at the diff.
How can I help you explore Laravel packages today?