PHPackages                             fasano/forms-bundle - 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. [Templating &amp; Views](/categories/templating)
4. /
5. fasano/forms-bundle

ActiveSymfony-bundle[Templating &amp; Views](/categories/templating)

fasano/forms-bundle
===================

Generate Symfony forms from your DTOs.

v1.0.0(1mo ago)11MITPHPPHP &gt;=8.4CI passing

Since May 9Pushed 4w agoCompare

[ Source](https://github.com/n-fasano/FormsBundle)[ Packagist](https://packagist.org/packages/fasano/forms-bundle)[ Docs](https://github.com/n-fasano/FormsBundle)[ RSS](/packages/fasano-forms-bundle/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (14)Versions (2)Used By (0)

 [![](formsbundle.png)](formsbundle.png)

[![Build Status](https://camo.githubusercontent.com/c69f5342593f5c0a9505be83219890b4dc9453b9b0317ae47d23a296f8e0b519/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636865636b2d72756e732f6e2d666173616e6f2f466f726d7342756e646c652f6d61696e3f7374796c653d666c61742d737175617265)](https://github.com/n-fasano/FormsBundle/actions?query=workflow:CI)[![Codecov](https://camo.githubusercontent.com/1b303cc73da935ca1c6095669fffb5859a7c8d63ec511d20b01875c39ea68fa5/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6e2d666173616e6f2f466f726d7342756e646c652f6d61696e3f7374796c653d666c61742d737175617265)](https://app.codecov.io/gh/n-fasano/FormsBundle)[![PHP Version](https://camo.githubusercontent.com/dd8cda238ddd5eff3d39aa995c84a6af5acce3e505bb8dc22d1aff6b2b700145/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f646570656e64656e63792d762f666173616e6f2f666f726d732d62756e646c652f5048503f7374796c653d666c61742d737175617265)](https://packagist.org/packages/fasano/forms-bundle)[![License](https://camo.githubusercontent.com/28dbc9b47e54ac604e711e7079daede3df424f62d1d0d429e4e9f928cbe45a6a/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6e2d666173616e6f2f466f726d7342756e646c653f7374796c653d666c61742d737175617265)](LICENSE)

Generate Symfony forms directly from your DTOs using PHP attributes - no more hand-writing `FormType` classes.

FormTypes are mostly derived information. Your property types determine the form type, nullability determines required, and validator constraints already encode things like email format, length bounds, and file types.

FormsBundle inspects your DTO's public properties, type hints, and attributes to automatically generate and cache fully functional Symfony forms.

Same form. Less boilerplate.
----------------------------

[](#same-form-less-boilerplate)

Declare the form once on the DTO and skip the hand-written Symfony `FormType`.

### ✅ With the bundle

[](#-with-the-bundle)

```
use Fasano\FormsBundle\Attribute\Form;
use Fasano\FormsBundle\Attribute\Field;
use Symfony\Component\Validator\Constraints as Assert;

#[Form\Options(action: 'app.contact', method: 'POST')]
#[Form\Button(label: 'Request')]
class ContactRequest
{
    #[Assert\Length(min: 2, max: 100)]
    public string $name;

    #[Assert\Email]
    public string $email;

    #[Assert\NotBlank]
    #[Assert\Length(max: 1000)]
    #[Field\Type(TextareaType::class)]
    public string $message;
}
```

Only your DTO remains - the bundle removes the extra boilerplate.

### ❌ Without the bundle

[](#-without-the-bundle)

```
use App\Dto\ContactRequest;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Validator\Constraints\Valid;

class ContactFormType extends AbstractType
{
    public function __construct(
        private UrlGeneratorInterface $urlGenerator
    ) {}

    public function buildForm(
        FormBuilderInterface $builder,
        array $options
    ): void {
        $builder
            ->add('name', TextType::class, [
                'attr' => ['minlength' => 2, 'maxlength' => 100],
            ])
            ->add('email', EmailType::class)
            ->add('message', TextareaType::class, [
                'attr' => ['maxlength' => 1000],
            ])
            ->add('submit', SubmitType::class, [
                'label' => 'Request',
            ]);
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'action' => $this->urlGenerator->generate('app.contact'),
            'method' => 'POST',
            'data_class' => ContactRequest::class,
        ]);
    }
}
```

Quick Start
-----------

[](#quick-start)

### 1. Install the bundle

[](#1-install-the-bundle)

```
composer require fasano/forms-bundle
```

Register the bundle (if not using Symfony Flex):

```
// config/bundles.php
return [
    // ...
    Fasano\FormsBundle\FormsBundle::class => ['all' => true],
];
```

### 2. Define a DTO

[](#2-define-a-dto)

```
use Fasano\FormsBundle\Attribute\Form;
use Fasano\FormsBundle\Attribute\Field;
use Symfony\Component\Validator\Constraints as Assert;

#[Form\Options(action: 'app.contact', method: 'POST')]
#[Form\Button(label: 'Request')]
class ContactRequest
{
    #[Assert\Length(min: 2, max: 100)]
    public string $name;

    #[Assert\Email]
    public string $email;

    #[Assert\NotBlank]
    #[Assert\Length(max: 1000)]
    #[Field\Type(TextareaType::class)]
    public string $message;
}
```

### 3. Create and use the form

[](#3-create-and-use-the-form)

```
use Fasano\FormsBundle\FormTypeFactory;

#[Route('/contact', name: 'app.contact', methods: ['GET', 'POST'])]
class ContactController extends AbstractController
{
    public function __construct(
        private FormTypeFactory $formFactory,
    ) {}

    public function __invoke(Request $request): Response
    {
        $form = $this->formFactory->createForm(ContactRequest::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $data = $form->getData(); // render('contact.html.twig', ['form' => $form]);
    }
}
```

That's it - no `ContactFormType` class needed.

How It Works
------------

[](#how-it-works)

`FormTypeFactory` reflects on your DTO, generates an `AbstractType` class, and caches it into `%kernel.cache_dir%/forms/`. The generated form type is built by deriving information from four data sources in sequence:

LayerSourceDerived informationTypesystemPHP typesinput type, label, requiredConstraints`#[Assert\...]` attributesinput type, HTML attributesTypeDocs`#[Name]`, `#[Description]`, `#[Example]`label, help, placeholderFormsBundle`#[Field\...]`, `#[Form\...]` attributesanything, always winsCaching is disabled when `APP_DEBUG` is on, so forms regenerate on every request during development.

Documentation
-------------

[](#documentation)

**Reference**

- [Features](docs/features.md) - type inference, nested DTOs, available attributes, constraint enrichment
- [Attributes](docs/attributes.md) - full `#[Form\...]` and `#[Field\...]` reference with parameters and examples

**Integrations**

- [Symfony Validator](docs/integrations/validator.md) - how constraints drive type selection and HTML attributes (72 constraints documented)
- [TypeDocs](docs/integrations/typedocs.md) - automatic labels, help text, and placeholders from type annotations
- [PHPrimitives](docs/integrations/primitives.md) - value object support with automatic data transformers

**Going deeper**

- [Extensibility](docs/extensibility.md) - custom field configurators and constraint configurators

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance94

Actively maintained with recent releases

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity51

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% 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

Unknown

Total

1

Last Release

31d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/16bb6f7b889777bcd3237bbddd90a3707306fc1803da0bd10c3710086b8702a4?d=identicon)[nfasano](/maintainers/nfasano)

---

Top Contributors

[![n-fasano](https://avatars.githubusercontent.com/u/46872160?v=4)](https://github.com/n-fasano "n-fasano (6 commits)")

---

Tags

bundlephpsymfonysymfony-bundlesymfony-forms

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/fasano-forms-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/fasano-forms-bundle/health.svg)](https://phpackages.com/packages/fasano-forms-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.5M370](/packages/easycorp-easyadmin-bundle)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.4M195](/packages/sulu-sulu)[chameleon-system/chameleon-base

The Chameleon System core.

1027.9k4](/packages/chameleon-system-chameleon-base)

PHPackages © 2026

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