Chapters
-
Course Code
Subscribe to download the code!Compatible PHP versions: ^7.1.3
Subscribe to download the code!Compatible PHP versions: ^7.1.3
-
This Video
Subscribe to download the video!
Subscribe to download the video!
-
Subtitles
Subscribe to download the subtitles!
Subscribe to download the subtitles!
-
Course Script
Subscribe to download the script!
Subscribe to download the script!
Field Types & Options
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
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".
Show Lines
|
// ... lines 1 - 10 |
class ArticleFormType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder | |
->add('title', TextType::class, [ | |
'help' => 'Choose something catchy!' | |
]) | |
Show Lines
|
// ... lines 19 - 20 |
} | |
Show Lines
|
// ... 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.
16 Comments
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!
oh i didn't know i could do that. Thank you for pointing out!
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?
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!
Sure, that had already been done before.
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
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.
Hey Viktor Z.
I think your best option is to create a new form with only *those* fields. Does it makes sense?
Cheers!
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.
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!
Hi!
https://github.com/luntik43...
The problem is in src/Form/ContactFormType.php and src/Controller/PagesController.php@contacts
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!
Is that a correct variant to use DTO and manually add data?
https://github.com/luntik43...
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!
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!
"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
"doctrine/annotations": "^1.0", // 1.10.2
"doctrine/doctrine-bundle": "^1.6.10", // 1.10.2
"doctrine/doctrine-migrations-bundle": "^1.3|^2.0", // v2.0.0
"doctrine/orm": "^2.5.11", // v2.7.2
"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
"phpdocumentor/reflection-docblock": "^3.0|^4.0", // 4.3.0
"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/cache": "^3.3|^4.0", // v4.1.6
"symfony/console": "^4.0", // v4.1.6
"symfony/flex": "^1.0", // v1.21.6
"symfony/form": "^4.0", // v4.1.6
"symfony/framework-bundle": "^4.0", // v4.1.6
"symfony/property-access": "^3.3|^4.0", // v4.1.6
"symfony/property-info": "^3.3|^4.0", // v4.1.6
"symfony/security-bundle": "^4.0", // v4.1.6
"symfony/serializer": "^3.3|^4.0", // v4.1.6
"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/stopwatch": "^3.3|^4.0", // v4.1.6
"symfony/var-dumper": "^3.3|^4.0", // v4.1.6
"symfony/web-profiler-bundle": "^3.3|^4.0" // v4.1.6
}
}
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?