PHPackages                             form-manager/form-manager - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. form-manager/form-manager

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

form-manager/form-manager
=========================

PHP-HTML form manager

v7.0.0(1y ago)16041.0k—0%45[1 issues](https://github.com/oscarotero/form-manager/issues)7MITPHPPHP &gt;=7.2CI passing

Since Jul 9Pushed 11mo ago12 watchersCompare

[ Source](https://github.com/oscarotero/form-manager)[ Packagist](https://packagist.org/packages/form-manager/form-manager)[ Docs](https://github.com/oscarotero/form-manager)[ RSS](/packages/form-manager-form-manager/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (7)Versions (69)Used By (7)

Form Manager
============

[](#form-manager)

[![Latest Version on Packagist](https://camo.githubusercontent.com/22e7bd8442417f2444e1a8e52b9a372706ea221bc29656cdc225cc88aa0a27a9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f666f726d2d6d616e616765722f666f726d2d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/form-manager/form-manager)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE)[![Testing](https://github.com/oscarotero/form-manager/workflows/testing/badge.svg)](https://github.com/oscarotero/form-manager/workflows/testing/badge.svg)[![Total Downloads](https://camo.githubusercontent.com/de9c4e7e4495663ca774214b8ac4c6b741b287fde9fe3b625b56061f38699829/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f666f726d2d6d616e616765722f666f726d2d6d616e616765722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/form-manager/form-manager)

> ### Note: this is the documentation of FormManager 7.x
>
> [](#note-this-is-the-documentation-of-formmanager-7x)
>
> For v6.x version [Click here](https://github.com/oscarotero/form-manager/tree/v6)

Installation:
-------------

[](#installation)

This package requires `PHP>=7.2` and is available on [Packagist](https://packagist.org/packages/form-manager/form-manager):

Supports `symfony/validator` v5, v6 and v7.

```
composer require form-manager/form-manager

```

Create a field
--------------

[](#create-a-field)

FormManager is namespaced, but you only need to import a single class into your context:

```
use FormManager\Factory as F;
```

Use the imported factory to create all form elements:

```
// Create an input type="text" element
$name = F::text();

// Create the input with a label
$name = F::text('Please, introduce your name');

// Or with extra attributes
$name = F::text('Please, introduce your name', ['class' => 'name-field']);

// Add or remove attributes
$name->setAttribute('title', 'This is the name input');
$name->removeAttribute('class');
$name->setAttributes([
    'required',
    'readonly',
    'tabindex' => 2,
    'maxlength' => 50
]);

// Set the value
$name->setValue('MyName');

// Use magic properties to get/set/remove attributes
$name->class = 'name-field';
$name->required = false;
unset($name->readonly);
```

### List of all available inputs:

[](#list-of-all-available-inputs)

All HTML5 field types are supported:

- `F::checkbox($label, $attributes)`
- `F::color($label, $attributes)`
- `F::date($label, $attributes)`
- `F::datetimeLocal($label, $attributes)`
- `F::email($label, $attributes)`
- `F::file($label, $attributes)`
- `F::hidden($value, $attributes)`
- `F::month($label, $attributes)`
- `F::number($label, $attributes)`
- `F::password($label, $attributes)`
- `F::radio($label, $attributes)`
- `F::range($label, $attributes)`
- `F::search($label, $attributes)`
- `F::select($label, $options, $attributes)`
- `F::submit($label, $attributes)`
- `F::tel($label, $attributes)`
- `F::text($label, $attributes)`
- `F::textarea($label, $attributes)`
- `F::time($label, $attributes)`
- `F::url($label, $attributes)`
- `F::week($label, $attributes)`

> Note that all inputs accepts the same arguments except `hidden` and `select`.

Validation
----------

[](#validation)

This library uses internally [symfony/validation](https://symfony.com/doc/current/validation.html) to perform basic html5 validations and error reporting. HTML5 validation attributes like `required`, `maxlength`, `minlength`, `pattern`, etc are supported, in addition to intrinsic validations assigned to each input like email, url, date, etc.

```
// Set global default error messages
F::setErrorMessages([
    'required' => 'The field is required'
    'maxlength' => 'The field is too long, it must have {{ limit }} characters or less',
]);

$email = F::email();

// Set per-fied error messages
$email->setErrorMessages([
    'email' => 'The email is not valid',
    'required' => 'The email is required',
    'maxlength' => 'The email is too long, it must have {{ limit }} characters or less',
]);

$email->setValue('invalid-email');

// Validate the value
if ($email->isValid()) {
    return true;
}

// Get the errors
$error = $email->getError();

// Print the first error message
echo $error;

// Iterate through all error messages
foreach ($error as $err) {
    echo $err->getMessage();
}

// And add more symfony constraints
$ip = F::text();
$ip->addConstraint(new Constraints\Ip());
```

See [all supported constraints by symfony/validation](https://symfony.com/doc/current/validation.html#supported-constraints).

Translations
------------

[](#translations)

This package allows you to set your custom Validation instance with `Factory::setValidator()`.

This allows you to use [symfony/translations](https://symfony.com/doc/current/translation.html) in order to have translations in place.

```
composer require symfony/translations
```

```
$validator = Validation::createValidatorBuilder()
    ->setTranslator($translator)
    ->setTranslationDomain('validators')
    ->getValidator();

// Set validator
F::setValidator($validator);
```

See [examples/translations.php](examples/translations.php) to see the full example.

Render html
-----------

[](#render-html)

```
$name = F::text('What is your name?', ['name' => 'name']);

echo $name;
```

```
What is your name?
```

Set a custom template using `{{ label }}` and `{{ input }}` placeholders:

```
$name->setTemplate('{{ label }} {{ input }}');
echo $name;
```

```
What is your name?
```

If you want to wrap the previous template in a custom html, use the `{{ template }}` placeholder:

```
$name->setTemplate('{{ template }}');
echo $name;
```

```
What is your name?
```

Grouping fields
---------------

[](#grouping-fields)

Group the fields to follow a specific data structure:

### Group

[](#group)

Groups allow to place a set of inputs under an specific name:

```
$group = F::group([
    'name' => F::text('Username'),
    'email' => F::email('Email'),
    'password' => F::password('Password'),
]);

$group->setValue([
    'name' => 'oscar',
    'email' => 'oom@oscarotero.com',
    'password' => 'supersecret',
]);
```

### Radio group

[](#radio-group)

Special case for radios where all inputs share the same name with different values:

```
$radios = F::radioGroup([
    'red' => 'Red',
    'blue' => 'Blue',
    'green' => 'Green',
]);

$radios->setValue('blue');
```

If you need the radio group to be required, you should add the `required` attribute to at least one radio button:

```
$radios = F::radioGroup([
    'red' => F::radio('Red', ['required' => true]),
    'blue' => 'Blue',
    'green' => 'Green',
]);
```

### Submit group

[](#submit-group)

Special case to group several submit buttons under the same name but different values:

```
$buttons = F::submitGroup([
    'save' => 'Save the row',
    'duplicate' => 'Save as new row',
]);

$buttons->setName('action');
```

### Group collection

[](#group-collection)

Is a collection of values using the same group:

```
$groupCollection = F::groupCollection(
    f::group([
        'name' => F::text('Name'),
        'genre' => F::radioGroup([
            'm' => 'Male',
            'f' => 'Female',
            'o' => 'Other',
        ]),
    ])
]);

$groupCollection->setValue([
    [
        'name' => 'Oscar',
        'genre' => 'm'
    ],[
        'name' => 'Laura',
        'genre' => 'f'
    ],
])
```

### Multiple group collection

[](#multiple-group-collection)

Is a collection of values using various groups, using the field `type` to identify which group is used by each row:

```
$multipleGroupCollection = F::multipleGroupCollection(
    'text' => f::group([
        'type' => F::hidden(),
        'title' => F::text('Title'),
        'text' => F::textarea('Body'),
    ]),
    'image' => f::group([
        'type' => F::hidden(),
        'file' => F::file('Image file'),
        'alt' => F::text('Alt text'),
        'text' => F::textarea('Caption'),
    ]),
    'link' => f::group([
        'type' => F::hidden(),
        'text' => F::text('Link text'),
        'href' => F::url('Url'),
        'target' => F::select([
            '_blank' => 'New window',
            '_self' => 'The same window',
        ]),
    ]),
]);

$multipleGroupCollection->setValue([
    [
        'type' => 'text',
        'title' => 'Welcome to my page',
        'text' => 'I hope you like it',
    ],[
        'type' => 'image',
        'file' => 'avatar.jpg',
        'alt' => 'Image of mine',
        'text' => 'This is my photo',
    ],[
        'type' => 'link',
        'text' => 'Go to my webpage',
        'href' => 'https://oscarotero.com',
        'target' => '_self',
    ],
]);
```

Datalist
--------

[](#datalist)

[Datalists](http://www.w3.org/TR/html5/forms.html#the-datalist-element) are also allowed, just use the `createDatalist()` method:

```
$input = F::search();

$datalist = $input->createDatalist([
    'female' => 'Female',
    'male' => 'Male'
]);

echo $input;
echo $datalist;
```

Forms
-----

[](#forms)

We need a form to put all this things together.

```
$loginForm = F::form([
    'username' => F::text('User name'),
    'password' => F::password('Password'),
    '' => F::submit('Login'),
]);

$loginForm->setAttributes([
    'action' => 'login.php',
    'method' => 'post',
]);

// mLoad data from globals $_GET, $_POST, $_FILES
$loginForm->loadFromGlobals();

// Load data passing the arrays
$loginForm->loadFromArrays($_GET, $_POST, $_FILES);

// Or load from PSR-7 server request
$loginForm->loadFromServerRequest($serverRequest);

// Get loaded data
$data = $loginForm->getValue();

// Print the form
echo $loginForm;

// Access to specific inputs:
echo $loginForm->getOpeningTag();
echo 'Login:';

echo $loginForm['username'];
echo '';
echo $loginForm['password'];
echo '';
echo $loginForm[''];
echo $loginForm->getClosingTag();

echo $loginForm->getOpeningTag();
echo 'Login:';

//nIterate through all inputs
foreach ($loginForm as $input) {
    echo "{$input}";
}
echo $loginForm->getClosingTag();
```

---

Please see [CHANGELOG](CHANGELOG.md) for more information about recent changes and [CONTRIBUTING](CONTRIBUTING.md) for contributing details.

The MIT License (MIT). Please see [LICENSE](LICENSE) for more information.

###  Health Score

54

—

FairBetter than 97% of packages

Maintenance50

Moderate activity, may be stable

Popularity47

Moderate usage in the ecosystem

Community35

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 78.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~64 days

Recently: every ~406 days

Total

68

Last Release

387d ago

Major Versions

v2.1 → v3.02013-11-18

v3.10.1 → v4.02015-02-26

v4.7.3 → v5.02016-05-04

v5.x-dev → v6.0.02018-12-24

v6.x-dev → v7.0.02025-04-26

PHP version history (5 changes)v0.1PHP &gt;=5.3.0

v5.0PHP &gt;=5.4.0

v6.0.0PHP ^7.1

v6.1.2PHP ^7.1 || ^8.0

v7.0.0PHP &gt;=7.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/e99df56b617f4af8cf0556a51a0ca20c7420104920c57d7e9eab093f92bb744f?d=identicon)[oscarotero](/maintainers/oscarotero)

![](https://www.gravatar.com/avatar/42e0d72f42eb7d84f67e20d28606da42e5a3248ca908b1eadb4366aafeae2561?d=identicon)[filisko](/maintainers/filisko)

---

Top Contributors

[![oscarotero](https://avatars.githubusercontent.com/u/377873?v=4)](https://github.com/oscarotero "oscarotero (317 commits)")[![filisko](https://avatars.githubusercontent.com/u/8798694?v=4)](https://github.com/filisko "filisko (38 commits)")[![eusonlito](https://avatars.githubusercontent.com/u/644551?v=4)](https://github.com/eusonlito "eusonlito (16 commits)")[![voronkovich](https://avatars.githubusercontent.com/u/2299535?v=4)](https://github.com/voronkovich "voronkovich (8 commits)")[![Patabugen](https://avatars.githubusercontent.com/u/196795?v=4)](https://github.com/Patabugen "Patabugen (5 commits)")[![buggedcom](https://avatars.githubusercontent.com/u/2810?v=4)](https://github.com/buggedcom "buggedcom (4 commits)")[![eshimischi](https://avatars.githubusercontent.com/u/983201?v=4)](https://github.com/eshimischi "eshimischi (3 commits)")[![DavidGoodwin](https://avatars.githubusercontent.com/u/203929?v=4)](https://github.com/DavidGoodwin "DavidGoodwin (2 commits)")[![dmitrijivanenko](https://avatars.githubusercontent.com/u/10165801?v=4)](https://github.com/dmitrijivanenko "dmitrijivanenko (2 commits)")[![endeveit](https://avatars.githubusercontent.com/u/197781?v=4)](https://github.com/endeveit "endeveit (2 commits)")[![davidrushton](https://avatars.githubusercontent.com/u/4039772?v=4)](https://github.com/davidrushton "davidrushton (1 commits)")[![8ig8](https://avatars.githubusercontent.com/u/241335?v=4)](https://github.com/8ig8 "8ig8 (1 commits)")[![carlos22](https://avatars.githubusercontent.com/u/526996?v=4)](https://github.com/carlos22 "carlos22 (1 commits)")[![m1](https://avatars.githubusercontent.com/u/978089?v=4)](https://github.com/m1 "m1 (1 commits)")[![scrutinizer-auto-fixer](https://avatars.githubusercontent.com/u/6253494?v=4)](https://github.com/scrutinizer-auto-fixer "scrutinizer-auto-fixer (1 commits)")[![SeifertDaniel](https://avatars.githubusercontent.com/u/9882400?v=4)](https://github.com/SeifertDaniel "SeifertDaniel (1 commits)")[![szepeviktor](https://avatars.githubusercontent.com/u/952007?v=4)](https://github.com/szepeviktor "szepeviktor (1 commits)")

---

Tags

form-builderformsvalidatordatahtmlform

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/form-manager-form-manager/health.svg)

```
[![Health](https://phpackages.com/badges/form-manager-form-manager/health.svg)](https://phpackages.com/packages/form-manager-form-manager)
```

###  Alternatives

[barbieswimcrew/zip-code-validator

Constraint class for international zipcode validation

772.3M](/packages/barbieswimcrew-zip-code-validator)[aura/input

This package contains tools to describe and filter user inputs from an HTML form, including sub-forms/sub-fieldsets, fieldset collections, an interface for injecting custom filter systems, and CSRF protection. Note that this package does not include output functionality, although the "hints" provided by the Form object can be used with any presentation system to generate an HTML form.

6678.4k4](/packages/aura-input)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
