Disclaimer: This article covers using Symfony Framework without the Doctrine ORM
As a follow-up on a conversation on Twitter, I decided to compile our dev team’s experience in using Symfony Forms for almost three years in production.
Domain & Type – Duplication
Splitting the form generation/handling into two parts was one of the biggest changes for us. We followed the Symfony guidelines and avoided polluting our controllers with
$this->createFormBuilder() but since we don’t use Doctrine entities, every form required us to make a dedicated domain object and a dedicated type object.
This led to us to duplicate a lot of form-related stuff. Symfony has very powerful validation and it’s a pity it has to be split across form domains and their corresponding types.
For example, you can
@Assert\Choice for a specific field, but you still have to repeat those choices when adding a ChoiceType; you can
@Assert\Type("integer") a field, but you still have to mark it as an IntegerType.
Now, I understand, splitting the form information from form representation is a good thing in theory, but in reality, it was more of a chore than a boost.
Our specific business case required us to build a lot of forms (133), so duplication hit us hard.
Following the official cookbook article to reduce duplication didn’t work for us, so we ended up not using
inherit_data. Eventually, using the plain OO inheritance proved better.
If you have to implement multi-step AJAX forms or have some kind of dependent AJAX filters in your form, chances are you’ll get an advice to use them.
We’ve found them so complicated (sometimes even impossible) to setup, test and debug that, if we had another opportunity, would skip using Symfony Forms in AJAX-heavy scenarios altogether.
Debugging Form Validation
Now, this may be because of the first issue – when validation is split between the domain and the type, it’s hard to find out which one caused it.
Or, this could be because of the modular nature of form building (every type inside a form type can have it’s own child type and so on), so it’s not so easy to flatten those errors and find out where and why it occurred.
Either way, every time a form
isValid returns false, we know we’re in for a serious head-scratching.
I didn’t mean for this to be a rant on Symfony Form component’s complexity.
It is a very sophisticated and thoroughly tested library we’d use on a project any day. It has helped us numerous times and we’re always discovering new ways in optimizing using it (it has changed a lot since we’ve started using it in Symfony 2.2).
The point I’m trying to get across is, while powerful, this library has a steep learning curve, a lot of gotchas and one needs really to master it in order to use it effectively, beyond the simplest use cases.