symfony form basics - oromeetup #3 cherkassy

55
Presentation title here Symfony Form “Make simple cases simple, make complex cases possible” - Bernhard Schussek presented by Andreii Yatsenko

Upload: andrew-yatsenko

Post on 16-Apr-2017

816 views

Category:

Engineering


2 download

TRANSCRIPT

Page 1: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

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

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

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

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

Presentation title here

How to create form?

● 2) using FormType

Page 8: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

How to set form data?

Page 10: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

Presentation title here

Always use objects instead of arrays!

Page 13: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

Why objects, I like kittens arrays?

Page 15: Symfony Form Basics - OroMeetup #3 Cherkassy

Presentation title here

Because of ValidationValidation

Page 16: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

$formFactory->createForm($formType, $data, $options);

Form options (configuration)

Page 18: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

Presentation title here

Next

Some form internals

Page 21: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

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

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

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

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

Presentation title here

Never inject dinamic objects to FormType!

Page 28: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

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

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

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

Presentation title here

Form Events

● PRE_SET_DATA● POST_SET_DATA

● PRE_SUBMIT● SUBMIT● POST_SUBMIT

Page 34: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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 37: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

How to solve this?

Page 39: Symfony Form Basics - OroMeetup #3 Cherkassy

Presentation title here

How to solve this?

FormTypeExtensions

Page 40: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

How form works with data internally?

Page 42: Symfony Form Basics - OroMeetup #3 Cherkassy

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

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

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

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

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

Presentation title here

Data Transformers

Register at $builder

$builder->get('date') ->addModelTransformer($transformer);

Page 48: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

Debugging Forms

Page 50: Symfony Form Basics - OroMeetup #3 Cherkassy

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

Presentation title here

How to test forms

Unit Test$builder = $this->createMock(“FormBuilder”);$builder->expects($this->at(1))->method(“add”)->withArguments(“username”, “text”)//...

Page 53: Symfony Form Basics - OroMeetup #3 Cherkassy

Presentation title here

Page 54: Symfony Form Basics - OroMeetup #3 Cherkassy

Presentation title here

Agenda

● Form Flow● Form EventListeners● Form Extensions● Data Transformers● Form Tests

Page 55: Symfony Form Basics - OroMeetup #3 Cherkassy

Presentation title here

?