Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Field Types & Options

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

Our form has an input text field and a textarea... which is interesting because, in our form class, all we've done is give each field a name. We... actually have not said anything about what "type" of field each should be.

But, we now know that, because we've bound our form to our entity, the form type "guessing" system is able to read the Doctrine metadata, notice that content looks like a big field, and "guess" that it should be a textarea.

Setting the Field Type

Field type guessing is cool! But... it's not meant to be perfect: we need a way to take control. How? It turns out that the add() method has three arguments: the field name, the field type and some options.

For title pass, TextType::class - the one from Form\Extensions. Go back to the form refresh and... absolutely nothing changes! Symfony was already "guessing" that this was a TextType field.

So Many Built-in Field Types

Google for "Symfony forms", click into the Symfony form documentation and find a section called "Built-in Field Types". Woh. It turns out that there are a ton of built-in field types. Yep, there's a field type for every HTML5 field that exists, as well as a few other, special ones.

Click into TextType. In addition to choosing which type you need, every type is super configurable. Many of these options are global, meaning, the options can be used for any field type. A good example is the label option: you can set a label option for any field, regardless of its type.

But other options are specific to that field type. We'll see an example in a minute.

Check out this help option: we can define a "help" message for any field. That sounds awesome! Back in the form class, add a third argument: an options array. Pass help and set it to "Choose something catchy".

... lines 1 - 10
class ArticleFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, [
'help' => 'Choose something catchy!'
])
... lines 19 - 20
}
... lines 22 - 28
}

Let's go check it out! Refresh! I like that! Nice little help text below the field.

The Form Profiler

This finally gives us a reason to check out one of the killer features of Symfony's form system. Look down at the web debug toolbar and find the little clipboard icon. Click that.

Yes! Say hello to the form profiler screen! We can see our entire form and the individual fields. Click on the title field to get all sorts of information about it. We're going to look at this several more times in this tutorial and learn about each piece of information.

Form Options in Profiler

Under "Passed Options" you can see the help option that we just passed. But, what's really cool are these "Resolved Options". This is a list of every option that was used to control the rendering & behavior of this one field. A lot of these are low-level and don't directly do anything for this field - like the CSRF stuff. That's why the official docs can sometimes be easier to look at. But, this is an amazing way to see what's truly going on under the hood: what are all the options for this field and their values.

And, yea! We can override any of these options via the third argument to the add() method. Without even reading the docs, we can see that we could pass a label option, label_attr to set HTML attributes on your label, or a required option... which actually has nothing to do with validation, but controls whether or not the HTML5 required attribute should be rendered. More on that later.

Anyways, let's add another, more complex field - and use its options to totally transform how it looks and works.

Leave a comment!

16
Login or Register to join the conversation
Dmytro K. Avatar
Dmytro K. Avatar Dmytro K. | posted 4 years ago

Why don't you add "use" statements in the script? Doesn't TextType require "use Symfony\Component\Form\Extension\Core\Type\TextType" ? I had the same issue with "'data_class' => Article::class" in the previous video. I know that PhpStorm can add use statements automatically, but i use Sublime. Do you intentionally skip adding use statements in order we could find proper class namespaces ourselves?

1 Reply

Hey Dmytro K.

Actually, that was my fault, I forgot to add the use statements to the scripts. So, sorry about that, but at least you can expand the code blocks and see the use statements

Cheers!

1 Reply
Dmytro K. Avatar

oh i didn't know i could do that. Thank you for pointing out!

1 Reply
Viktor Z. Avatar
Viktor Z. Avatar Viktor Z. | posted 4 years ago

Hi!
Unfortunately, "isValid" check fails with exceptions. They tell, that "createdAt" and "updatedAt" fields are null and that's impossible (I use TimestampableEntity in my entity class).
How can I fix that?

Reply

Hey Viktor Z.

If you installed "StofDoctrineExtensionBundle", then you may have forgotten to activate the Timestampable extension


stof_doctrine_extensions:
    orm:
        default:
            timestampable: true

cheers!

Reply
Viktor Z. Avatar

Sure, that had already been done before.

Reply

Hmm, that's odd. If you have the extension activated and you are using the TimestampableEntity treat on your entity, it should just work. I think I'll need to see your code.
Also, just in case, try clearing the cache manually


rm -rf var/cache
Reply
Viktor Z. Avatar

I've found that issue: https://github.com/symfony/....
So, I've the same problem: I need the form (with data_class) to pass the validation but doesn't have "required by entity class" fields in form.
Is there a way to validate only posted form fields because required fields for entity which are not created by form will be created manually in controller.

Reply

Hey Viktor Z.

I think your best option is to create a new form with only *those* fields. Does it makes sense?

Cheers!

Reply
Viktor Z. Avatar

Unfortunately, I cannot completely understand you.
I’ll try to explain again what I mean :))
1) I’ve created a Form Class which is connected with an Entity Class via “data_class” parameter.
2) There are some required fields in connected Entity Class.
3) I don’t want a user fill all required entity fields in a form, so I call “add” method of “builder” only for those fields I want the user to fill.
4) When I call “is_valid” method inside controller, I can’t pass checks, because in controller I fetch an entity class object from a form but this object obviously doesn’t include entity class required fields.

So I want to call “set” methods for required fields manually in controller after I fetch object from form.

Reply

Hmm, I get what you are saying but I don't get why validations are not passing if the submitted form is indeed valid. From what you said I assume you are editing an User object. So, if you submit a valid form it should just work, unless you have, for some strange reason, invalid users on your Database. If that's not the case, then I'm missing something, probably would be useful if I can see your code. Just upload to anywhere (Github) and send me a link to it :)

Cheers!

Reply
Viktor Z. Avatar

Hi!
https://github.com/luntik43...
The problem is in src/Form/ContactFormType.php and src/Controller/PagesController.php@contacts

Reply

Hey Viktor Z.

I now understand your problem better. Here what you can do:
A) Create a DTO (Data transfer object) holding only the fields you want to submit, attach the class to your form and on submit, you will have to manually attach the other part of the data to your Support entity and then save it into the database. Or
B) Use the $clearMissing parameter. The only gotcha is that you will have to modify a bit how you handle POST requests but I'll leave you with the docs (they are easy to follow) and a video where Ryan uses it, but if you have more questions, feel free to ask us :)

Docs: https://symfony.com/doc/current/form/direct_submit.html
Video: https://symfonycasts.com/screencast/symfony-rest/patch-programmer

Cheers!

Reply
Viktor Z. Avatar

Is that a correct variant to use DTO and manually add data?
https://github.com/luntik43...

Reply
Viktor Z. Avatar

Unfortunately, your B variant didn't help.
I've updated the repository with the newest code.
Now I use PATCH method to submit the form, and set $clearMissing parameter to false.
https://github.com/luntik43...
The problem is still in src/Form/ContactFormType.php and src/Controller/PagesController.php@contacts

UPDATED: I've just used validation_groups and now there is no problem with 'topic' field, but there are still errors with time stamps. With validation_groups I don't need to use $clearMissing at all.
You can see the changes in commit history.

Thanks a lot!

Reply

Hey Viktor

I'm glad to know that you could fix your problem and of course, validation groups! They are great when the data model doesn't change but the constraints do depending on the action

Cheers!

Reply
Cat in space

"Houston: no signs of life"
Start the conversation!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-iconv": "*",
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "knplabs/knp-markdown-bundle": "^1.7", // 1.7.0
        "knplabs/knp-paginator-bundle": "^2.7", // v2.8.0
        "knplabs/knp-time-bundle": "^1.8", // 1.8.0
        "nexylan/slack-bundle": "^2.0,<2.2.0", // v2.0.0
        "php-http/guzzle6-adapter": "^1.1", // v1.1.1
        "sensio/framework-extra-bundle": "^5.1", // v5.2.1
        "stof/doctrine-extensions-bundle": "^1.3", // v1.3.0
        "symfony/asset": "^4.0", // v4.1.6
        "symfony/console": "^4.0", // v4.1.6
        "symfony/flex": "^1.0", // v1.17.6
        "symfony/form": "^4.0", // v4.1.6
        "symfony/framework-bundle": "^4.0", // v4.1.6
        "symfony/orm-pack": "^1.0", // v1.0.6
        "symfony/security-bundle": "^4.0", // v4.1.6
        "symfony/serializer-pack": "^1.0", // v1.0.1
        "symfony/twig-bundle": "^4.0", // v4.1.6
        "symfony/validator": "^4.0", // v4.1.6
        "symfony/web-server-bundle": "^4.0", // v4.1.6
        "symfony/yaml": "^4.0", // v4.1.6
        "twig/extensions": "^1.5" // v1.5.2
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.0", // 3.0.2
        "easycorp/easy-log-handler": "^1.0.2", // v1.0.7
        "fzaninotto/faker": "^1.7", // v1.8.0
        "symfony/debug-bundle": "^3.3|^4.0", // v4.1.6
        "symfony/dotenv": "^4.0", // v4.1.6
        "symfony/maker-bundle": "^1.0", // v1.8.0
        "symfony/monolog-bundle": "^3.0", // v3.3.0
        "symfony/phpunit-bridge": "^3.3|^4.0", // v4.1.6
        "symfony/profiler-pack": "^1.0", // v1.0.3
        "symfony/var-dumper": "^3.3|^4.0" // v4.1.6
    }
}
userVoice