gstreamer0.10-ffmpeg
gstreamer0.10-plugins-good
packages.
Tip
This screencast shows the old, 2.7 and earlier form syntax. But, the code blocks below have been updated to show the new syntax!
Now that we've got our entity let's create a form! Click on AppBundle, press our handy shortcut command+n
, and if you search form you'll find that option in the menu! It's all coming together!
We'll call this MovieType
:
namespace AppBundle\Form; | |
use Symfony\Component\Form\AbstractType; | |
use Symfony\Component\Form\FormBuilderInterface; | |
use Symfony\Component\OptionsResolver\OptionsResolver; | |
class MovieType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
} | |
public function configureOptions(OptionsResolver $resolver) | |
{ | |
} | |
} |
Notice it was actually smart enough to put that inside of a Form
directory and build out the whole structure that we'll need. All I need next is for it to pour me a cup of coffee.
The first thing we always do inside of here is call $resolver->setDefaults(array())
and pass the data_class
option so that it binds it to our Movie
entity. Conveniently, this gives us more autocomplete: we can just type Movie
and it adds the rest:
... lines 1 - 8 | |
class MovieType extends AbstractType | |
{ | |
... lines 11 - 15 | |
public function configureOptions(OptionsResolver $resolver) | |
{ | |
$resolver->setDefaults(array( | |
'data_class' => 'AppBundle\Entity\Movie' | |
)); | |
} | |
} |
This will even help us build our fields. If we type $builder->add('')
here, because this is bound to our Movie
entity, it knows all the properties we have there. So let's plug in our property of title
which should be a text
field, samsCharacterName
which is probably a text field as well and isMainCharacter
which will be a checkbox. We'll want to make sure that we prevent html5 validation on that. A third argument of 'required' => false
will take care of that for us and even that has autocomplete. It's madness!
... lines 1 - 5 | |
use Symfony\Component\Form\Extension\Core\Type\CheckboxType; | |
... lines 7 - 8 | |
use Symfony\Component\Form\Extension\Core\Type\TextType; | |
... lines 10 - 12 | |
class MovieType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder->add('title', TextType::class) | |
->add('samsCharacterName', TextType::class) | |
->add('isMainCharacter', CheckboxType::class, array( | |
'required' => false, | |
)) | |
... lines 22 - 25 | |
} | |
... lines 27 - 33 | |
} |
Let's also include rating
as an integer field and lastly, releasedAt
which is a date field:
... lines 1 - 6 | |
use Symfony\Component\Form\Extension\Core\Type\DateType; | |
use Symfony\Component\Form\Extension\Core\Type\IntegerType; | |
use Symfony\Component\Form\Extension\Core\Type\TextType; | |
... lines 10 - 12 | |
class MovieType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder->add('title', TextType::class) | |
... lines 18 - 21 | |
->add('rating', IntegerType::class) | |
->add('releasedAt', DateType::class, array( | |
... line 24 | |
)); | |
} | |
... lines 27 - 33 | |
} |
We can control how this date field renders: by default with Symfony it would be 3 select boxes. I'll set a widget
option, except I don't remember what value to set that to. No worries, I'll just hold the command key over the widget
option and it will take me straight to where that is setup inside of the core code:
... lines 1 - 11 | |
namespace Symfony\Component\Form\Extension\Core\Type; | |
... lines 13 - 26 | |
class DateType extends AbstractType | |
{ | |
const DEFAULT_FORMAT = \IntlDateFormatter::MEDIUM; | |
... lines 30 - 167 | |
public function configureOptions(OptionsResolver $resolver) | |
{ | |
... lines 170 - 202 | |
$resolver->setDefaults(array( | |
... lines 204 - 206 | |
'widget' => 'choice', | |
... lines 208 - 224 | |
)); | |
... lines 226 - 235 | |
$resolver->setAllowedValues('widget', array( | |
'single_text', | |
'text', | |
'choice', | |
)); | |
... lines 241 - 245 | |
} | |
... lines 247 - 321 | |
} |
Why is that awesome you ask? Because I can search for what I need inside of here and boom setAllowedValues
single_text
, text
and choice
. So let's paste single_text
back into our file.
... lines 1 - 6 | |
use Symfony\Component\Form\Extension\Core\Type\DateType; | |
... line 8 | |
use Symfony\Component\Form\Extension\Core\Type\TextType; | |
... lines 10 - 12 | |
class MovieType extends AbstractType | |
{ | |
public function buildForm(FormBuilderInterface $builder, array $options) | |
{ | |
$builder->add('title', TextType::class) | |
... lines 18 - 22 | |
->add('releasedAt', DateType::class, array( | |
'widget' => 'single_text' | |
)); | |
} | |
... lines 27 - 33 | |
} |
That trick of holding command and clicking works for the field types too: command+click integer
and suddenly you're inside the class that provides this!
... lines 1 - 11 | |
namespace Symfony\Component\Form\Extension\Core\Type; | |
... lines 13 - 19 | |
class IntegerType extends AbstractType | |
{ | |
... lines 22 - 37 | |
public function configureOptions(OptionsResolver $resolver) | |
{ | |
... lines 40 - 47 | |
$resolver->setDefaults(array( | |
// deprecated as of Symfony 2.7, to be removed in Symfony 3.0. | |
'precision' => null, | |
// default scale is locale specific (usually around 3) | |
'scale' => $scale, | |
'grouping' => false, | |
// Integer cast rounds towards 0, so do the same when displaying fractions | |
'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN, | |
'compound' => false, | |
)); | |
... lines 58 - 69 | |
} | |
... lines 71 - 78 | |
} |
It's like being teleported but, you know, without any risk to your atoms. You can even use this to take you to the property inside of Movie
for that specific field.
Our form is setup so let's go ahead and create this inside of our controller, $form = $this->createForm(new MovieType(), $movie);
. Like always, we need to pass our form back into our template with $form->createView()
:
... lines 1 - 5 | |
use AppBundle\Form\MovieType; | |
... lines 7 - 10 | |
class MovieController extends Controller | |
{ | |
... lines 13 - 15 | |
public function newAction() | |
{ | |
$movie = new Movie(); | |
$form = $this->createForm(MovieType::class, $movie); | |
return $this->render('movie/new.html.twig', array( | |
'quote' => 'If my answers frighten you then you should cease asking scary questions. (Pulp Fiction)', | |
'form' => $form->createView() | |
)); | |
} | |
... lines 27 - 34 | |
} |
Time to render this! Click into the new.html.twig
template, ah that's right my form is actually going to be over here in _form.html.twig
. It shouldn't surprise you that you'll get autocomplete here on things like form_start
and form_end
:
{{ form_start(form) }} | |
... lines 2 - 8 | |
{{ form_end(form) }} |
Want more autocomplete awesomeness you say? You're mad! But ok: type {{ form_row(form) }}
and it'll auto-complete the title
field for you. So we'll plug in all of our fields here:
{{ form_start(form) }} | |
{{ form_row(form.title) }} | |
{{ form_row(form.samsCharacterName) }} | |
{{ form_row(form.isMainCharacter) }} | |
... lines 5 - 8 | |
{{ form_end(form) }} |
And if I forget one of them, I can hit control+space
to bring up all of my options. This will also show you some other methods that exist on that FormView
object. Ah ok so we still have rating
and releasedAt
to add here. Clean up a bit of indentation here and perfect!
{{ form_start(form) }} | |
{{ form_row(form.title) }} | |
{{ form_row(form.samsCharacterName) }} | |
{{ form_row(form.isMainCharacter) }} | |
{{ form_row(form.rating) }} | |
{{ form_row(form.releasedAt) }} | |
<button type="submit" class="btn btn-primary">Save</button> | |
{{ form_end(form) }} |
Time to try this out: back to our new movies page, refresh and there we go! It renders with no problems other than the fact that this is a form only it's developer could love. And well, maybe not even that: I'm going to make it prettier. In config.yml
, down in the twig
key add form_themes
:
... lines 1 - 34 | |
twig: | |
... lines 36 - 37 | |
form_themes: | |
... lines 39 - 83 |
Now this should autocomplete, but for whatever reason this one key is not doing that. But for the most part, you will see autocompletion inside of your configuration files.
Right here let's plug in the bootstrap form theme: and the plugin isn't perfect because we don't get autocomplete on this either. But I do know that there is a file inside the project for bootstrap, so I'll go to find, file and start typing in bootstrap. We want the one called bootstrap_3_layout.html.twig
. To cheat, I'll just copy that file name and paste that in here:
... lines 1 - 34 | |
twig: | |
... lines 36 - 37 | |
form_themes: | |
- bootstrap_3_layout.html.twig | |
... lines 40 - 83 |
Refresh with our new form theme and .... Awesome!
When I tried to reload my new form I got exeption:
Expected argument of type "string", "AppBundle\Form\MovieType" given
I have changed :
$form = $this->createForm(new MovieType(), $movie);
for:
$form = $this->createForm(MovieType::class, $movie);
Got new:
Could not load type "text"
500 Internal Server Error - InvalidArgumentException
Your comments suggestions would be greatly appreciated
Hey Andrew!
You've already got the right fix actually! This tutorial was on Symfony 2, where we did things like "new MovieType" and ->add('someField', 'text'). In Symfony 3, change it to MovieType::class (you already did this) *and* make a similar change in your form class - e.g. ->add('someField', TextType::class); That'll fix things :).
Cheers!
I literally wrote this and then saw you solved the issue yourself :). Thanks for posting the detailed update! https://knpuniversity.com/s...
Does this still work. I am using Ubuntu 20.04 with latest version of PhpStorm with Symfony5 and I initiated the project with the full option
symfony new --full my_project.
I don't see any of the options in the new menu. Just one option for symfony service and when click on that nothing happens as well. I uninstalled and re-installed the symfony support plugin and enabled it as well for the project.
Hey Graymath technology
I believe Symfony plugin people dropped that feature because I can't do it either but the good news is you don't need it anymore, you can generate any boiler plate file by using the MakerBundle. It's a super handy bundle that you should give it a try https://symfony.com/doc/cur...
Cheers!
I did all as you do, but when my form is rendered the field 'Released at' does not display
'mm/dd/yyyy' inside , just empty. Could you give me, please, any hint how to fix it.
Hey Andrew!
You're probably doing it correctly :). Symfony renders this fields as an input type="date" field. *Some* browsers (like mine - Chrome) are smart enough to turn that into a "smart" field - that's what you're seeing. I (and Symfony) did *not* add that mm/dd/yyyy - my browser is adding that because it knows this is a date field. If you try Chrome, you will likely see that same behavior. But even if you don't, you can just fill in the field with something like 06/20/2000 and it will submit. If you'd like to have a fancy date picker in *all* browsers, you should use a JavaScript library to help the user fill in the right date (e.g. 06/20/2000).
Cheers!
Probably my Google Chrome is silly and don't displayt mm/dd/yyyy either.
From your point of view , is Chrome more advanced for web development now then Fox?
Best regards!
Ah, so strange! I mostly prefer Chrome because I like its native web inspector better! I *do* (for whatever reason) see it used by most developers, probably with Safari second.
Hello, first thanks to Andrew for the solution with the 500 error, I had the same problem.
I have another question, I have bootstrap under web/vendors/bootstrap, but the code has no effect. Inspect shows that the bootstrap classes are there, but the page looks the same as before, is it a path problem?
thanks.
Hello there!!! i`m in love with Symfony and KNPU... I have a question... There is a way to render the fields of FORM in columns? like [ 'class'=>'col-md-3' ]??? I`m not founding where to change the variables... thanks!!!
Hi Raphael!
Ah, thank you so much!!!! I'm glad you love both things :p.
I might have an easy answer to your question: have you tried the bootstrap_3_horizontal_layout.html.twig form theme? It organizes labels and fields into columns: https://github.com/symfony/...
You can configure to use this form theme in the same way as the other bootstrap form theme.
Cheers!
Help! I'm not getting completion on the add type fields. eg in $builder->add('title','text') "text" is not completing. What is missing? So much going on so quickly I'm not sure what I might have missed. I tab completed the add call so assume all the right "usages" are in. But all I have are:
namespace AppBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
OK. the code below doesn't match the video. The correct syntax for 3.2 is : $builder->add('title',TextType::class) which is in the code forms but not in the video. Or am I going doolally? ;)
Yo Richard ,
Yes, you're right, code blocks related to the Symfony forms mismatch the video. We updated code blocks to use the new Symfony 3 syntax, but not the video. Btw, we have a note about it at the beginning of this article: https://knpuniversity.com/s... ;)
Cheers!
Hey Richard ,
If you're on Symfony 3 - you should use `TextType::class` as you figured out below by yourself. The 'text' way is deprecated and doesn't work since Symfony 3.
Cheers!
The same exception was thrown when I tried to reload the form page (expected argument of type string ...).
I finally found a solution to fix it.
I REPLACED >> "$form = $this->createForm(new MovieType(), $movie);"
BY >> "form = $this->get('form.factory')->create(MovieType::class, $movie);"
I also used fully-qualified class name in the buildForm function (as described by there ) .
Yep, you guys are absolutely right - the "new MovieType" was one of the changes that was deprecated in 2.x and removed for Symfony 3.x (replaced with the MoveType::class form). That's the key change to make :).
I'm using PHPStorm on Ubuntu OS.
When I'm trying to create new Form or Controller nothing happens when I click on 'New->Form' or 'New->Controller'
Hey Paulius!
So, you have the New->Form and New->Controller options, but they don't do anything when you click them? Or are the options missing? If clicking them does nothing, that sounds like some sort of a bug with the Symfony plugin.
Hmm, I've never seen that before, unfortunately :(. You could try re-installing the plugin/phpstorm - it's the best advice I can give!
I have PHPstorm on my windows7 and symfony 3.
When I try (Ctrl + click) over 'widget' I do not get to Core/Type/DateType.php as you do but see "Can't find declaration to go to".
All the same for 'integer'. What can it be?
Hi Andrew!
Do you have the Symfony plugin installed and (more importantly) enabled for this project? That's the most likely cause - let me know! *Sometimes* things won't work, even when you have the plugin installed+enabled, but I don't have problems with forms usually.
Cheers!
// composer.json
{
"require": {
"php": ">=5.3.9, <7.3.0",
"symfony/symfony": "2.8.*", // v2.8.15
"doctrine/orm": "^2.4.8", // v2.4.8
"doctrine/dbal": "<2.5", // v2.4.5
"doctrine/doctrine-bundle": "~1.4", // 1.6.4
"symfony/assetic-bundle": "~2.3", // v2.8.1
"symfony/swiftmailer-bundle": "~2.3,>=2.3.10", // v2.4.2
"symfony/monolog-bundle": "^3.0.2", // v3.0.2
"sensio/distribution-bundle": "~5.0", // v5.0.17
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.18
"incenteev/composer-parameter-handler": "~2.0" // v2.1.2
},
"require-dev": {
"sensio/generator-bundle": "~3.0", // v3.1.2
"symfony/phpunit-bridge": "~2.7" // v2.8.15
}
}
I found the issue.
WAS OK BEFORE(sf 2.8):
$builder->add('title', 'text')
->add('samsCharacterName', 'text')
->add('isMainCharacter', 'checkbox', array(
'required' => false
))
->add('rating', 'integer')
->add('releasedAt', 'date', array(
'widget' => 'single_text',
));
SHOULD BE (from sf 2.8):
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
$builder->add('title', TextType::class)
->add('samsCharacterName', TextType::class)
->add('isMainCharacter', CheckboxType::class, array(
'required' => false
))
->add('rating', IntegerType::class)
->add('releasedAt', DateType::class , array(
'widget' => 'single_text',
));