Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Application Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

nette/application is the Nette MVC kernel, not a Laravel package. It will not slot into a Laravel app as a replacement for controllers, Blade, or Eloquent. Its natural home is a Nette application with Nette DI, nette/routing, nette/http, and Latte. If you are evaluating it from a Laravel background, treat it as a different framework layer: Presenter is roughly controller + view model + lifecycle, Control is a reusable widget/component, and signal is a component-scoped request handler.

Start with the Nette sandbox rather than assembling dependencies manually:

composer create-project nette/web-project my-app
# or, in an existing Nette project:
composer require nette/application

A minimal entry point looks like this:

// www/index.php
require __DIR__ . '/../vendor/autoload.php';

$configurator = new Nette\Bootstrap\Configurator;
$configurator->setDebugMode(true);
$configurator->enableTracy(__DIR__ . '/../log');
$configurator->setTempDirectory(__DIR__ . '/../temp');
$configurator->createRobotLoader()
    ->addDirectory(__DIR__ . '/../app')
    ->register();
$configurator->addConfig(__DIR__ . '/../app/config/common.neon');

$container = $configurator->createContainer();
$container->getByType(Nette\Application\Application::class)->run();

Then create your first presenter:

namespace App\Presenters;

use Nette\Application\UI\Presenter;

final class HomepagePresenter extends Presenter
{
    public function renderDefault(): void
    {
        $this->template->title = 'Home';
    }
}

Place the template at app/Presenters/templates/Homepage/default.latte:

{block content}
<h1>{$title}</h1>
<p>Hello from Latte.</p>
{/block}

Where to look first:

  1. Presenter lifecycle and action methods (render<Action>, action<Action>, beforeRender, afterRender).
  2. Nette\Application\UI\Control and createComponent<Name>().
  3. Links and signals: {link}, n:href, handle<Signal>().
  4. Routing: RouteList, route masks, presenter/action mapping.
  5. Latte templating and the UI macros ({control}, {snippet}, {link}).

First real use case: build one page with a layout, a presenter, a reusable control, and a signal that mutates state and redirects or invalidates a snippet. That single flow exercises the majority of what you will use day to day.

Mental model for Laravel developers:

Laravel Nette Application
Controller Presenter
Blade view Latte template
route('name') {link Presenter:action} / LinkGenerator
Reusable view component Control with its own template and signals
Form request + controller action nette/forms component + onSuccess callback
Service container constructor injection Nette DI constructor injection

Implementation Patterns

Presenter lifecycle is the primary workflow. Use startup() for shared setup, beforeRender() for data needed by the template, render<Action>() for GET-style page rendering, and handle<Signal>() for state-changing requests. Keep action parameters in method signatures rather than reading them manually.

use Nette\Application\Attributes\Persistent;

final class ArticlePresenter extends Presenter
{
    #[Persistent]
    public int $page = 1;

    public function renderDetail(int $id): void
    {
        $this->template->article = $this->articles->get($id);
    }

    public function handleDelete(int $id): void
    {
        $this->articles->delete($id);
        $this->flashMessage('Article deleted.');
        $this->redirect('this');
    }
}

Use components for anything reusable. A component is a full sub-request with its own template, signals, and lifecycle. This is the package’s main architectural advantage over controller-only frameworks.

protected function createComponentCommentForm(): Nette\Application\UI\Form
{
    $form = new Nette\Application\UI\Form;
    $form->addText('name')->setRequired();
    $form->addTextArea('text')->setRequired();
    $form->addSubmit('send', 'Post comment');
    $form->onSuccess[] = [$this, 'commentFormSucceeded'];
    return $form;
}

public function commentFormSucceeded(Nette\Application\UI\Form $form, array $values): void
{
    $this->comments->add($values['name'], $values['text']);
    $this->flashMessage('Comment posted.');
    $this->redirect('this');
}

Template usage:

{control commentForm}

Use signals for component-scoped actions. Signal links use an exclamation mark:

<a n:href="delete! $article->id">Delete</a>

The corresponding handler is handleDelete(int $id). For AJAX-driven components, update a snippet and invalidate it:

public function handleIncrement(): void
{
    $this->count++;
    $this->invalidateControl('counter');
}
{snippet counter}
    <strong>{$count}</strong>
{/snippet}

Generate links through the presenter/LinkGenerator, not by hand. Inside presenters and templates, use {link} or $this->link(). For emails, CLI jobs, or URLs generated outside a request context, inject Nette\Application\LinkGenerator and use withReferenceUrl() where appropriate. Link aliases added in 3.2.x are useful for keeping URLs stable while renaming presenters.

Use attributes for cross-cutting request requirements. Recent 3.2.x releases add #[Requires], #[Deprecated], #[Parameter], and #[TemplateVariable]. They are useful for login/role/method checks, deprecating actions, parameter metadata, and typed template properties. Do not mistake #[Requires] for a full authorization system: pair it with nette/security and a real authorizator.

Inject services through constructors. Since 3.2.1, injected presenter services are readonly. Prefer explicit constructor injection over $this->context-style service location.

public function __construct(
    private readonly ArticleRepository $articles,
) {
    parent::__construct();
}

Handle errors with the application’s error presenter. Use $this->error('Not found', 404) for aborting a request, and configure application.error4xxPresenter / errorPresenter for user-facing error pages. Let catchExceptions remain enabled in production; it is silently deprecated as a manual toggle in newer releases.

Test at the boundaries. Use Nette Tester for presenters/control logic, and test link generation through LinkGenerator. For forms and components, test the callbacks and services rather than trying to emulate the entire HTTP kernel. Keep presenter tests small: one action render, one signal, one form success path.

Gotchas and Tips

  • This is not Laravel-compatible. Do not install it into a Laravel app expecting controller integration. It expects Nette DI, Nette HTTP, and Latte. If you need Laravel, use Laravel; if you need Nette, commit to the Nette stack.
  • Version requirements are real. The 3.2 line requires PHP 8.1+ and Latte 3.1. Release notes show support for PHP 8.4/8.5, but your other dependencies may lag. Pin nette/application and Latte versions in composer.json.
  • The license metadata says NOASSERTION. Nette packages are typically BSD-3-Clause, but verify the actual license file before adopting it in a commercial or redistributed product.
  • Signals must be public. Private signal methods throw. Also remember that signals are not automatically CSRF-protected; use forms with CSRF protection for mutations, and combine #[Requires] with application-level authorization.
  • Do not output before redirects. redirect() terminates the request via an exception. Any earlier output or partially rendered template will cause problems.
  • Persistent parameters have sharp edges. #[Persistent] properties should be initialized or safely typed. Defaults on #[Parameter] are not passed to link generation in 3.2.8, which can produce unexpected URLs. Prefer action method arguments for ordinary request parameters.
  • Link generation validates aggressively. LinkGenerator throws when linking to #[Requires(forward: true)] targets (3.2.9). Check invalidLinkMode when debugging link exceptions, and prefer {link}/n:href over manually concatenated URLs.
  • Template resolution is convention-based. render<Action>() maps to templates/<Presenter>/<action>.latte; custom template classes and findTemplateFile() can change this. In 3.2.7, a template’s default property is not assigned if it does not match the expected type. Type your template properties carefully.
  • Template is abstract in 3.2.7+. If you subclassed it directly, adjust to the current hierarchy (Template → DefaultTemplate). Also note the 3.1 change from magic __get/__set to real object properties.
  • Latte extension ordering matters. If you create templates through a custom LatteFactory, add the UI extension or pass the control so {control}, {link}, and snippets work. UI macros such as {control} need the Latte UI extension; xhtml is deprecated.
  • Snippets only make sense in AJAX responses. Use {snippet}/{snippetArea} and invalidateControl(). Multiple-template snippet rendering was fixed in 3.2.7; if you render more than one template, upgrade rather than debugging stale snippet state.
  • Presenter mapping and scanning are config-sensitive. Check application.mapping and the scanDir/scanFilter pattern (*Presenter by default). The ** mapping supports Foo/FooPresenter layouts. Clear the temp/cache directory after changing DI or mapping configuration.
  • Debug with Tracy and the built-in panels. Enable Tracy in development, use the RoutingPanel to inspect route matching, and use {templatePrint} / the Latte panel to inspect template parameters. Most link and routing issues are visible there before you add logging.
  • MicroPresenter is for prototypes. It is handy for tiny demos and closures, but it is intentionally limited; do not build a large application around it.
  • Performance comes from DI compilation and Latte caching. Keep constructors and startup() light, avoid expensive work in every presenter, and ensure opcache and the temp directory are configured correctly in production.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator