Symfony Form Basics - OroMeetup #3 Cherkassy
-
Upload
andrew-yatsenko -
Category
Engineering
-
view
816 -
download
2
Transcript of Symfony Form Basics - OroMeetup #3 Cherkassy
![Page 1: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/1.jpg)
Presentation title here
Symfony Form
“Make simple cases simple, make complex cases possible”
- Bernhard Schussek
presented by Andreii Yatsenko
![Page 2: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/2.jpg)
Presentation title here
About me
● Я Андрюха● PHP Developer at Oro Inc.● Live in Kyiv● Studied at GeekHub ~3 years ago● 6 years with PHP
![Page 3: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/3.jpg)
Presentation title here
Agenda
● Form Flow● Form EventListeners● Form Extensions● Data Transformers● Form Tests
● Bad and Good Practices● Almost W/O code samples
![Page 4: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/4.jpg)
Presentation title here
Form flow
● create form● set data to form● handle request● Profit! do something with updated data
○ E.g. persist data to DB
![Page 5: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/5.jpg)
Presentation title here
How to create form?At first ● you need to create formFactory● or if you are using Symfony just get it from
ServiceContainer
$formFactory = $container->get(“form.factory”);
![Page 6: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/6.jpg)
Presentation title here
How to create form?
● 1) using FormBuilder in Controller :($formFactory->createFormBuilder()
->add(‘firstName”)->add(“lastName”)->add(“email”);
![Page 7: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/7.jpg)
Presentation title here
How to create form?
● 2) using FormType
![Page 8: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/8.jpg)
Presentation title here
How to create form?
● If you in Controller$this->createForm($formType)// or$this->createFormBuilder()
->add(“name”, “text”)->getForm();
![Page 9: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/9.jpg)
Presentation title here
How to set form data?
![Page 10: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/10.jpg)
Presentation title here
Always set form data at form creation!
$data = new User();$formFactory
->createForm($formType, $data, $options);// or$formFactory->createFormBuilder($data);
![Page 11: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/11.jpg)
Presentation title here
Try to not setData after form creation
Because● All form events will be triggered twice :(
$form = $formFactory->createForm($formType);
$form->setData($data);
![Page 12: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/12.jpg)
Presentation title here
Always use objects instead of arrays!
![Page 13: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/13.jpg)
Presentation title here
If you don’t have object - you just not created it yet!
● Create DTO
![Page 14: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/14.jpg)
Presentation title here
Why objects, I like kittens arrays?
![Page 15: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/15.jpg)
Presentation title here
Because of ValidationValidation
![Page 16: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/16.jpg)
Presentation title here
How to Validate Form
● Do not validate form!● Validate data
○ yaml, xml, annotation drivers for constrants
● But what if my form doesn’t submit the data? ○ like “Apply terms checkbox”
● Make field mapped = false and validate form
![Page 17: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/17.jpg)
Presentation title here
$formFactory->createForm($formType, $data, $options);
Form options (configuration)
![Page 18: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/18.jpg)
Presentation title here
Form options (configuration)
● Form options is a form configuration. And it’s a data too, data that needed for building and submitting the form, but it’s not the Form Data (Usually don’t need to be updated from user input)
![Page 19: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/19.jpg)
Presentation title here
Form options (configuration)
● Buy the way Form Data is an option too. You can just set $options[‘data’], and form factory internally use it too. It’s have higher priority than $data (second param) in
$formFactory->createForm($type, $data, $options)
![Page 20: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/20.jpg)
Presentation title here
Next
Some form internals
![Page 21: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/21.jpg)
Presentation title here
How form saves your memory
In Symfony2 all form fields are forms too, and can be reused.
E.x. ● TextFormType● CategoryFormType● ProductFormType● etc.
![Page 22: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/22.jpg)
Presentation title here
How form saves your memory
Form composed from ● Form (form builder template etc.) and● FormConfig (options with data)
● Form and FormConfig are different objects.
![Page 23: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/23.jpg)
Presentation title here
How form saves your memory
When you reuse Form, e.x. if you create form with 20 text fields, only ONE TextForm will be created.
![Page 24: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/24.jpg)
Presentation title here
How form saves your memory
● But for different fields you have different data, and usually different options, they are so called FormConfig and will be created for each fields, so in our example you will have 20 FormConfig objects
![Page 25: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/25.jpg)
Presentation title here
How to create form, that depends on data?● Use dependency injections:inject data to FormType container
E.x. new FormType($someData);
![Page 26: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/26.jpg)
Presentation title here
• How to create form, that depends on data?● Use dependency injections:inject data to FormType container
E.x. new FormType($someData);
![Page 27: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/27.jpg)
Presentation title here
Never inject dinamic objects to FormType!
![Page 28: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/28.jpg)
Presentation title here
Never inject dinamic objects to FormType!
Because you will change FormType, not the FormConfig, so all forms on page will be configured the same.
![Page 29: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/29.jpg)
Presentation title here
The right way :)
● Inject to container static objects E.x. Doctine, not concrete Entities
![Page 30: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/30.jpg)
Presentation title here
If I don’t have static object? :(
● Use custom form options
$formFactory->createFrom($type, $data, $options);
At first you need to configure them in FormType::configureOptions()
![Page 31: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/31.jpg)
Presentation title here
But wait, Where to place dinamic business logic, if I can’t place it in FormType?
:(
![Page 32: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/32.jpg)
Presentation title here
But wait, Where to place dinamic business logic, if I can’t place it in FormType?
In EventListeners! :)
![Page 33: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/33.jpg)
Presentation title here
Form Events
● PRE_SET_DATA● POST_SET_DATA
● PRE_SUBMIT● SUBMIT● POST_SUBMIT
![Page 34: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/34.jpg)
Presentation title here
How to subscribe to form events?
1) Create:● EventListener - any callable● EventSubscriber - separate class
implementedSymfony\Component\EventDispatcher\EventSubscriberInterface
2) Add them to FormBuilder
$builder->addEventListener(“PRE_SUBMIT”, $listener);
$builder->addEventSubscriber($subscriber)
![Page 35: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/35.jpg)
Presentation title here
You can even change the form in EventListeners● add or remove form fields
http://symfony.com/doc/current/components/form/form_events.html
![Page 36: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/36.jpg)
Presentation title here
You can even change the form in EventListeners● but in Symfony you can’t change or
replace form field
In OroPlatform we have FormUtils that solve this problemhttps://github.com/orocrm/platform/blob/936c1bfcff34c2381a31fa40726d518d3f6ab0b8/src/Oro/Bundle/FormBundle/Utils/FormUtils.php
![Page 37: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/37.jpg)
Presentation title here
But you can’t register event listener like in symfony or doctrine EventDispatcher, from another bundle
![Page 38: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/38.jpg)
Presentation title here
How to solve this?
![Page 39: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/39.jpg)
Presentation title here
How to solve this?
FormTypeExtensions
![Page 40: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/40.jpg)
Presentation title here
FormTypeExtensions● Like form types but have getExtendedType()
method● extends Symfony\Component\Form\AbstractTypeExtension
● Registered in DI with tag form.type_extension
![Page 41: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/41.jpg)
Presentation title here
How form works with data internally?
![Page 42: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/42.jpg)
Presentation title here
How form works with data internally?
E.x. DateTimeFormType● You set to form timestamp
● User will see human formatted string
![Page 43: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/43.jpg)
Presentation title here
How form works with data internally?
E.x. DateTimeFormType● You set to form timestamp● In EventListeners you work with DateTime ● User will see human formatted string
![Page 44: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/44.jpg)
Presentation title here
How form works with data internally?
E.x.● Controller - timestamp● Form - DateTime ● User - formatted string
![Page 45: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/45.jpg)
Presentation title here
How form works with data internally?
E.x.● Model Data - timestamp● Normalized Data - DateTime ● View Data - formatted string
![Page 46: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/46.jpg)
Presentation title here
Data Transformers● Model Transformer● View Transformer
implement Symfony\Component\Form\DataTransformerInterface
2 methods:● transform($data)● reverseTransform($data)
![Page 47: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/47.jpg)
Presentation title here
Data Transformers
Register at $builder
$builder->get('date') ->addModelTransformer($transformer);
![Page 48: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/48.jpg)
Presentation title here
Data Transformers
● Should only transform data from one format to another, but never change the data.
● If you want to change data use EventListeners
![Page 49: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/49.jpg)
Presentation title here
Debugging Forms
![Page 50: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/50.jpg)
Presentation title here
How to test forms
Unit Test$builder = $this->createMock(“FormBuilder”);$builder->expects($this->at(1))->method(“add”)->withArguments(“username”, “text”)//...
![Page 51: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/51.jpg)
Presentation title here
How to test forms
Unit Test$builder = $this->createMock(“FormBuilder”);$builder->expects($this->at(1))->method(“add”)->withArguments(“username”, “text”)//...
![Page 52: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/52.jpg)
Presentation title here
How to test forms
● Write Integrational tests \Symfony\Component\Form\Test\FormIntegrationTestCaseE.x.https://github.com/laboro/b2b/blob/9d18a036099357b04d41116ca2dfcaa57a59163c/src/OroB2B/Bundle/AccountBundle/Tests/Unit/Form/Extension/CategoryFormExtensionTest.php#L34-L34
![Page 53: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/53.jpg)
Presentation title here
![Page 54: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/54.jpg)
Presentation title here
Agenda
● Form Flow● Form EventListeners● Form Extensions● Data Transformers● Form Tests
![Page 55: Symfony Form Basics - OroMeetup #3 Cherkassy](https://reader034.fdocuments.net/reader034/viewer/2022052606/58f3883b1a28ab70778b4583/html5/thumbnails/55.jpg)
Presentation title here
?