nette/forms
Robust PHP form library from Nette for building and validating HTML forms. Provides reusable controls, CSRF protection, server-side validation with clear error handling, rendering helpers, and strong integration with Nette applications for secure, maintainable form workflows.
Installation:
composer require nette/forms
For Laravel integration (standalone), add to composer.json:
"require": {
"nette/forms": "^3.2"
}
Basic Form Creation:
use Nette\Forms\Form;
use Nette\Forms\Controls\TextInput;
$form = new Form();
$form->addText('username', 'Username:')
->addRule(Form::MIN_LENGTH, 'Too short', 3)
->addSubmit('send', 'Send');
// Handle submission
$form->onSuccess[] = function ($form) {
$values = $form->getValues();
// Process $values['username']
};
Rendering in Blade:
echo $form->render();
Or use Latte (if integrated) with {formPrint $form}.
Create a login form with validation:
$form = new Form();
$form->addText('email', 'Email')
->addRule(Form::EMAIL, 'Invalid email')
->addPassword('password', 'Password')
->addRule(Form::MIN_LENGTH, 'Too short', 6)
->addSubmit('login', 'Login');
$form->onSuccess[] = function ($form) {
$email = $form->getValue('email');
// Authenticate user
};
Form Initialization & Submission:
// In Laravel controller
public function create(Form $formFactory) {
$form = $formFactory->create();
// Add controls, rules, etc.
return view('form.view', ['form' => $form]);
}
public function handle(Form $formFactory, Request $request) {
$form = $formFactory->get($request->get('form_id'));
if ($form->isSubmitted() && $form->isValid()) {
$values = $form->getValues();
// Process
}
return redirect()->back();
}
Dynamic Forms (Laravel + DI):
// Register in `services.php`
$container->addService('formFactory', function () {
return new Nette\Forms\Container();
});
// Usage
$form = $container->get('formFactory');
$form->addText('dynamic_field')->addRule(Form::FILLED);
Validation Rules:
// Built-in rules
$form->addText('age')->addRule(Form::INTEGER, 'Must be integer')
->addRule([$form, 'validateAge'], 'Too young');
// Custom validator
public function validateAge($value, Form $form) {
return $value >= 18 || $form->addError('Must be 18+');
}
Client-Side Validation:
// Auto-generated via `netteForms.js`
$form->addText('name')->addRule(Form::MIN_LENGTH, 'Too short', 2);
// Renders with `data-nette-rules="minLength:2"`
File Uploads:
$form->addUpload('avatar')
->addRule(Form::MAX_FILE_SIZE, 'Too large', 5 * 1024 * 1024)
->addRule(Form::IMAGE, 'Must be image');
{{ $form->render() }} or extract controls:
@foreach ($form->getControls() as $control)
<div>{{ $control->getLabel() }}</div>
{{ $control->getControl()->render() }}
@endforeach
{formPrint $form}.SameSite cookies).if (!$form->isValid()) {
foreach ($form->getErrors() as $error) {
echo $error->getMessage();
}
}
Validation Scope:
getValues() returns only validated controls by default. Use:
$form->getValues(true); // All values (including invalid)
getValues() in v3.2+ respects setValidationScope().Latte Dependency:
{formPrint}) require Latte. For Blade-only apps:
use Nette\Forms\Rendering\DefaultFormRenderer;
$renderer = new DefaultFormRenderer();
echo $renderer->render($form);
Client-Side Rules:
data-nette-rules are validated client-side. Explicitly add rules:
$form->addText('field')->addRule(Form::FILLED)->setHtmlAttribute('data-nette-rules', 'filled');
Enum Support:
addEnum() with BackedEnum:
enum Status { ACTIVE, INACTIVE }
$form->addEnum('status', Status::class);
Hidden Fields:
addHidden() accepts any type (unlike setDefaultValue):
$form->addHidden('user_id')->setValue($user->id);
Validation Errors:
$form->getErrors() for form-level errors and $control->getErrors() for field-specific issues.addRule(Form::CUSTOM, 'Custom message') for granular control.CSRF Issues:
SameSite cookies are supported (PHP 8.1+). For older PHP:
$form->setHtmlAttribute('data-nette-csrf', true);
File Uploads:
upload_max_filesize in PHP.ini and use:
$form->addUpload('file')->addRule(Form::MAX_FILE_SIZE, null, 10 * 1024 * 1024);
Type Safety:
$form->addText('age')->addRule(Form::INTEGER)->setType('int');
Custom Validators:
class CustomValidator extends Nette\Forms\Validator {
public function validate($value, Form $form) {
return $value === 'secret' || $form->addError('Invalid');
}
}
$form->addText('secret')->addRule(new CustomValidator());
Override Rendering:
$renderer = new DefaultFormRenderer();
$renderer->setElementPrototype('div', '<div class="form-group">%html%</div>');
echo $renderer->render($form);
Dynamic Controls:
$form->addDynamic('dynamic_field')
->addRule(Form::FILLED)
->onValidate[] = function ($control, $value) {
if (empty($value)) {
$control->addError('Required');
}
};
Laravel Service Provider:
// app/Providers/NetteFormsServiceProvider.php
public function register() {
$this->app->singleton('form.factory', function () {
return new Nette\Forms\Container();
});
}
Blueprint Generation:
Blueprint for DTOs:
use Nette\Forms\Blueprint;
$blueprint = new Blueprint($form);
$blueprint->generate('UserDto.php');
How can I help you explore Laravel packages today?