Chapters
41 Chapters
|
4:45:40
|
Login to bookmark this video
-
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!
25.
Custom Field: configureOptions() & Allowing Empty Input
Scroll down to the script below, click on any sentence (including terminal blocks) to jump to that spot in the video!
Subscribe to jump to this part in the video!
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
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
}
}
15 Comments
Very good and clear videos about those custom types.
Hey Coder,
Thank you for your feedback! We are happy to hear it's clear and easy to understand :)
Cheers!
Hi! When we make a new form, we create some *FormType class which derives from the AbstractType class. And when we want to customise some field we also need to extend AbstractType. This looks like a mess (for now). A whole form vs just a single field. What's the logic behind this?
Hey Yuri,
You could write that code in the same (AtriclyType) form class, but separate that logic allows you to reuse that UserSelectTextType in other forms, and just makes code clearer: now it's 2 small classes instead of one big that holds all the mixed logic inside. But yeah, I see your point. It's simple when you have simple tasks, but complicates and require more work when your tasks become more complex. But this approach is flexible and allows you to build really complex forms that might be nested to each other and where some parts could be re-used in other forms.
Cheers!
Hi Victor, thank you for your response. Separation is great, no problem with that. But I was confused that the form and the form element are represented by the identical class. Intuitively the whole form and just the single element are very different "entities". Well, maybe I should use it in practice for some time to get the idea.
Hey Yuri,
Yeah, I see your point, but that's the one of many things that makes Symfony Forms so powerful. With this implementation your form behaves as a nested tree, and thanks to this you can make more complex and nested forms, as you can easily put one form into another form, inside another form and so on :) Yeah, definitely, the more practice - the better understanding. Also, go with Symfony Docs about the Form component will helps to understand it better and cover blind spots.
Cheers!
Hi, thanks for the video. I have a question tho. :)
Is there a general rule on where the form validation should be? It is shown that when a user is not found you can implement that with an exception in the data transformer, while if the input is empty the validation is done on the entity proper via `@Assert\NotNull()`. I would assume it is technically possible to also add an exception to the data transformer to check for the input not being null, but would that be a bad practice?
Hey RobinBastiaan!
That's a very smart question :). The short answer is that, yes, you could really put all of your validation rules into a data transformer. I'm not saying you should, but you definitely *could* do this. You wouldn't be able to customize the error the users sees based on different wrong values (e.g. "this field is required" vs "this field needs more characters"), but it would work. One other difference is that, if you fail in a data transformer, the submitted value is never set back onto your object.
Anyways, the general rule for where each should live comes down to what I call "sanity validation" vs "business rules" validation. Entering the word "apple" for a NumberType::class field is an "insane" value: there is no sane way for us to take "apple" and find a "number" that we could set back onto your object. And so, we fail. The same is true for a ChoiceType::class, if the user (it would require some HTML hacking) submitted a value that is *not* in the choice list. That is simply an "insane" value.
The idea is: if a value is at least "sane", then allow it to be set onto your object. And THEN use the normal validation. The normal validation has all those nice, built-in validators anyways, and you can customize different errors per failure type.
Let me know if this helps!
Cheers!
Why are we allowing to enter a null author value in the entity when it is set as not nullable in the database? Wouldn't null be an "insane" value for author in that case if it will eventually throw an exception when saved to the database?
Hey Oscar Z.!
Hmm, I see your point! I guess where the "is this insane" line is drawn is in PHP itself. What I mean is: in PHP, for example, it is "insane" to set an "int" property to a string. But, it's not considered "insane" to set null to a property that allows null (in PHP), even though it would explode in the database if you actually saved it that way. So, I hear what you're saying... this is more of an explanation of the thinking behind this :).
Of course, this whole philosophy assumes that you are "ok" with your entity objects being in an "invalid" state temporarily: (A) the form sets some data into your object... including data you may consider invalid and then (B) that data is validated. There is a minority (but decent-sized group of people) who don't like this, and instead create dedicated DTO objects that they bind to the forms (instead of entities). They allow these DTOs to be "invalid" and have validation applied to them. Then, they do some extra work (after validation is successful) to "transfer" the data from the DTO onto the entity. The advantage is that your entity can always be in a "valid" state. I don't personally use this approach, as it requires a good deal more work, but it is totally valid.
Cheers!
What's the difference between if (null === $value) and if (!$value) ?
Hey Farry7,
With "null === $value" you have strict (Identical) comparison, when check both values and types. With "!$value" the value of the variable is. converted to boolean first, and then you revert boolean value to the opposite. See more info and examples in PHP docs: https://www.php.net/manual/...
Cheers!
Hi there !
In the tutorials, you usually use the function sprintf in the Exception error message, instead of just passing a string (which can be concatenate with a variable).
Is there any reason for that?
Hey Stileex,
It's just a matter of taste ;) Well, sprintf() came from another languages where usually it's the standard way of putting some dynamic vars into a string. Yes, PHP has concatenation so you can totally use it instead. Or, you can even put vars directly in the string with double quotes - it should work as well. But depends on the length of your variables, and if you need to call some getters on the objects, etc. - it might be more readable to use sprintf(). So, it depends, but it's totally up to you. There might be some performance improvements using one or another option... but those should be too minor to think about.
I hope this helps!
Cheers!
Thanks for your reply Victor :)
"Houston: no signs of life"
Start the conversation!