POSTS
Configurable Required Fields for Symfony Forms
Shame shame shame on me… still writing about symfony not 2 when all the momentum has gone to a version th
at brings things to the next level. However I’ll talk about things related to the form framework here and from what I hear, a lot of this has been kept in symfony2. Whether true or not, many out there will keep working on symfony 1.x for a while because well the project already exists / has to be maintained or keep going and new symfony version doesn’t mean that every website using it will change and update tomorrow! So this should still be good info!
If you are developing a website that only runs one instance, this most likely won’t be really interesting for you. However if what you are creating is meant to be installed by many (or at least a few) who will want to customize forms and tweak it their way, then maybe you’ll find some info here.
The problem I was trying to solve here is this: Mr. A and Mr. B are both using that brand new shiny e-commerce platform you’re creating. However Mr. A is selling standard books and Mr. B is selling art books! See the difference? Well for Mr. B, he can’t live without his articles having the printing quality of the book description attached to them on his website. Is it quadri-chromography? Laser printing? Hand painting? Stuff? Different printing stuff? So when he inputs an article in the database, the book field named ‘Print quality’ in the form HAS TO BE set! It’s a mandatory field for him but Mr. A doesn’t give a sh#! about printing quality.
What we need
To provide those two people with the availability to decide which form fields are or not required on their articles, we need a place to configure those things (for me it’s a configuration setting in a YAML file, but for you it could be in the database), we need each form to find those and dynamically adapt which forms are or not required so that the validation part will fail if we receive no input. And of course it would be nice if we could display those required fields differently to the user (underlined? little star at the end of the label?…).
The YAML file is really easy, in Symfony, each form (most of them) has a name. Use this name as your config key and then list all the required fields (by their names). And it’ll look like this:
Make it work!
Lucky as we are, symfony forms come with a very weird and complex awesome (but still a bit complex to get) inheritance. And when you create a symfony project and have all your forms generated by Doctrine maybe, well you can also notice a BaseForm.class in your /lib/form/ folder. This is a base class that is NOT in a base folder. This is not a class that will be rewritten / erased ever. And ALL generated forms have it as their parent somewhere in the inheritance chain.
Forms are customized through their configure() method. In here you can add / remove widgets and … AND! validators. Usually there is no configure method defined in any parent class and your forms don’t call parent::configure(). So we’re going to use this one, and yes … from now on your forms will actually need to call parent::configure(). But that’s the only modification that will have to be made on every form. Anything else will be done in the BaseForm class. And all of this is just standard and nice class inheritance, no weird hack or anything.
We need 2 things: set the validator’s required option to true on the fields we receive. And then set a special css class to the field’s label so we can later customize the look. Here it goes:
What else?
Not much is left to do now. In each form, make sure that you make a call to parent::configure() AFTER you made all your configurations. If there’s no widgets / validators yet, it’s no use trying to modify them.
All we need is to define that required_form_field CSS class. What I chose is to display a ‘*’ at the end of the label, using the :after css selector. But this is completely up to you! Mine:
That’s it! Now I (and you too) can decide for each install which fields are going to be required or not. If you need highly customizable things, say your not creating an e-commerce system but a platform, and you host everything, you could store this kind of configuration somewhere else (per-client in the DB for example) and customize it differently for each user on the fly.