nette/forms
Nette Forms is a PHP form-building library for creating secure, reusable web forms with built-in validation, CSRF protection, rendering helpers, and easy component composition. Integrates smoothly with Nette Framework but works standalone in any PHP app.
Installation:
composer require nette/forms
For Laravel integration, use nette/forms alongside nette/di (dependency injection) and latte/latte (if using Latte templates).
Basic Form Creation:
use Nette\Forms\Container;
use Nette\Forms\Controls\TextInput;
$form = new Container();
$form->addText('username', 'Username')
->addRule($form::MIN_LENGTH, 'Too short', 3)
->addRule($form::MAX_LENGTH, 'Too long', 50);
First Use Case:
{!! $form->render() !!}
public function handleForm(Container $form)
{
if ($form->isSubmitted() && $form->isValid()) {
$values = $form->getValues();
// Process $values['username']
}
}
Container, Controls, and Validators).$form->addGroup('Personal Info')
->addText('firstName')
->addText('lastName');
$form->addDynamic('tags', function (Container $form, $name) {
return $form->addTextInput($name);
});
$email = $form->addEmail('email')
->addRule($form::EMAIL, 'Invalid email')
->addRule($form::FILLED, 'Email is required');
$form->addRule(function ($value) {
return strlen($value) > 10 || 'Must be >10 chars';
});
// app/Providers/AppServiceProvider.php
public function register()
{
$this->app->bind('nette.form.factory', function () {
return new \Nette\Forms\FormFactory();
});
}
use Nette\Forms\FormFactory;
public function __construct(FormFactory $formFactory) {
$this->formFactory = $formFactory;
}
$form->setRenderer(new \Nette\Forms\Renderers\DefaultFormRenderer());
echo $form->render();
netteForms.js for real-time validation (e.g., data-nette-rules attributes).$user = new User();
$form->setValues($user); // Hydrates object properties
$form->getValues($user); // Validates and updates object
$upload = $form->addUpload('avatar')
->addRule($form::MAX_FILE_SIZE, 'Too large', 5 * 1024 * 1024);
if ($form->isSubmitted() && $upload->isValid()) {
$upload->getFile()->move(__DIR__ . '/uploads');
}
{form $form}
{input username}
{input email}
{submit 'Save'}
{/form}
CSRF Protection:
isSameSite() checks). Disable with:
$form->setCsrfProtection(false);
Validation Scope:
getValues() only returns controls in the validation scope (BC break in v3.1+). Use:
$form->getValues(true); // Force all values (deprecated in v3.2+)
getUntrustedValues() for raw POST data.Enum Hydration:
getValues(MyEnum::class) requires PHP 8.1+ and BackedEnums. For older PHP:
$form->addSelect('status', ['active', 'inactive'])
->setDefaultValue('active');
Client-Side Validation Quirks:
netteForms.js only validates elements with data-nette-rules. Ensure:
$form->setRenderer(new \Nette\Forms\Renderers\DefaultFormRenderer());
$control->setDisabled(true)) are skipped in client validation.Upload Limits:
UploadControl auto-sets MAX_FILE_SIZE, but check upload_max_filesize in php.ini for consistency.Latte Template Caching:
{form}, {input}) cache aggressively. Clear cache after form changes:
$latte->addFilter('form', function () { return true; }); // Force refresh
Validation Errors:
$form->getErrors() for server-side errors.netteForms.js logs).Hidden Fields:
addHidden() for non-editable values:
$form->addHidden('user_id')->setValue(auth()->id());
Type Safety:
Container::getValue(). Use:
$value = $form->getValue('field', 'default');
Event Handling:
$form->onSubmit[] = function ($form) {
if ($form->isValid()) { /* ... */ }
};
Custom Renderers:
DefaultFormRenderer for Bootstrap/Tailwind:
class BootstrapRenderer extends DefaultFormRenderer {
protected function renderControl(Control $control) {
return '<div class="form-group">' . parent::renderControl($control) . '</div>';
}
}
Dynamic Rules:
addRule() with closures for runtime validation:
$form->addText('password')
->addRule(function ($value) use ($user) {
return $value === $user->getPassword() || 'Incorrect';
});
Blueprints:
$blueprint = new \Nette\Forms\Blueprint($user);
$form = $blueprint->create();
Modal Forms:
netteForms.js modals:
Nette.showModal('#my-form', {title: 'Confirm'});
PHP 8.1+ Features:
BackedEnum for getValues() mapping.addInteger(), addFloat() for strict typing.Deprecated Methods:
getValues(true) (use getUntrustedValues()).addImage() with addImageButton().Latte-Specific:
{inputError} requires a control argument:
{inputError email 'Invalid email'}
How can I help you explore Laravel packages today?