Everything you always wanted to know about forms* *but were afraid to ask
-
Upload
andrea-giuliano -
Category
Technology
-
view
2.716 -
download
5
description
Transcript of Everything you always wanted to know about forms* *but were afraid to ask
![Page 1: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/1.jpg)
SYMFONYDAY 2013
Everything you always wanted to know about forms*
*but were afraid to ask
@bit_sharkAndrea Giuliano
![Page 2: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/2.jpg)
TreeAbstract Data Structure
![Page 3: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/3.jpg)
Andrea Giuliano @bit_shark
…
collection of nodes each of which has an associated value and a list of children connected to their parents by means of an edge
Tree: Abstract data Type
![Page 4: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/4.jpg)
Andrea Giuliano @bit_shark
Symfony Forms are trees
Form
Form Form Form
Form
![Page 5: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/5.jpg)
Andrea Giuliano @bit_shark
Example: a meeting form
![Page 6: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/6.jpg)
Andrea Giuliano @bit_shark
Let’s create it with Symfony
namespace MyApp\MyBundle\Form;!!use Symfony\Component\Form\AbstractType;!use Symfony\Component\Form\FormBuilderInterface;!use Symfony\Component\OptionsResolver\OptionsResolverInterface;!!class MeetingType extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $option)! {! $builder->add('name', 'string');! $builder->add('when', 'date');! $builder->add('featured', 'checkbox');! }!! public function getName()! {! return 'meeting';! }!}
![Page 7: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/7.jpg)
Andrea Giuliano @bit_shark
Meeting
form
Symfony’s point of view
![Page 8: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/8.jpg)
Andrea Giuliano @bit_shark
$builder->add('name', 'string')
Meeting
form
Namestring
Symfony’s point of view
![Page 9: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/9.jpg)
Andrea Giuliano @bit_shark
$builder->add('when', 'date')
Meeting
form
Namestring
Datedate
Month
choice
Day
choice
Year
choice
Symfony’s point of view
![Page 10: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/10.jpg)
Andrea Giuliano @bit_shark
Meeting
form
Namestring
Datedate
Month
choice
Day
choice
Year
choice
Symfony’s point of view
$builder->add('featured', 'checkbox')
Featuredcheckbox
![Page 11: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/11.jpg)
Data format
![Page 12: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/12.jpg)
Andrea Giuliano @bit_shark
class Form implements \IteratorAggregate, FormInterface!{! [...]!! /**! * The form data in model format! */! private $modelData;!! /**! * The form data in normalized format! */! private $normData;!! /**! * The form data in view format! */! private $viewData;!}
Data format
![Page 13: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/13.jpg)
Andrea Giuliano @bit_shark
How the information is represented in the application model
Data format
Model Data
Norm Data
View Data
![Page 14: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/14.jpg)
Andrea Giuliano @bit_shark
Data format
Model Data
Norm Data
View Data
How the information is represented in the view domain
![Page 15: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/15.jpg)
Andrea Giuliano @bit_shark
Data format
Model Data
Norm Data
View Data
???
![Page 16: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/16.jpg)
Andrea Giuliano @bit_shark
$builder->add('when', 'date')
widget View Data
choice array
single_text string
input Model Data
string string
datetime DateTime
array array
timestamp integer
Meeting
form
Datedate
Model Data and View Data
![Page 17: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/17.jpg)
Andrea Giuliano @bit_shark
widget View Data
choice array
single_text string
input Model Data
string string
datetime DateTime
array array
timestamp integer
Meeting
form
Datedate
Model Data and View Data
What $form->getData() will return?
![Page 18: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/18.jpg)
Andrea Giuliano @bit_shark
Which format would you like to play with in your application logic?
$form->getNormData()
Normalized Data
![Page 19: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/19.jpg)
Data Transformers
![Page 20: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/20.jpg)
Andrea Giuliano @bit_shark
Data transformersclass BooleanToStringTransformer implements DataTransformerInterface!{! private $trueValue;!! public function __construct($trueValue)! {! $this->trueValue = $trueValue;! }!! public function transform($value)! {! if (null === $value) {! return null;! }!! if (!is_bool($value)) {! throw new TransformationFailedException('Expected a Boolean.');! }!! return $value ? $this->trueValue : null;! }!! public function reverseTransform($value)! {! if (null === $value) {! return false;! }!! if (!is_string($value)) {! throw new TransformationFailedException('Expected a string.');! }!! return true;! }!}
![Page 21: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/21.jpg)
Andrea Giuliano @bit_shark
Model Data
Norm Data
View Data
Model Data
Norm Data
View Data
transform() transform()
reverseTransform() reverseTransform()
Model Transformer View Transformer
Data transformers
![Page 22: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/22.jpg)
Andrea Giuliano @bit_shark
Data transformers
class MeetingType extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $option)! {! $transformer = new MyDataTransformer();!! $builder->add('name', 'string');! $builder->add('when', 'date')->addModelTransformer($transformer);! $builder->add('featured', 'checkbox');! }!! public function getName()! {! return 'meeting';! }!}!
Add a ModelTransformer or a ViewTransformer
![Page 23: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/23.jpg)
Andrea Giuliano @bit_shark
Data transformers
class MeetingType extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $option)! {! $transformer = new MyDataTransformer(/*AnAwesomeDependence*/);!! $builder->add('name', 'string');! $builder->add('when', 'date')->addModelTransformer($transformer);! $builder->add('featured', 'checkbox');! }!! public function getName()! {! return 'meeting';! }!}!
in case of dependencies?
![Page 24: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/24.jpg)
Andrea Giuliano @bit_shark
![Page 25: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/25.jpg)
Andrea Giuliano @bit_shark
Data transformers
Use it by creating your own type
<service id="dnsee.type.my_text" ! class="Dnsee\MyBundle\Form\Type\MyTextType">!
<argument type="service" id="dnsee.my_awesome_manager"/>! <tag name="form.type" alias="my_text" />!</service>
![Page 26: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/26.jpg)
Andrea Giuliano @bit_shark
Data transformers
Use it by creating your own type
class MyTextType extends AbstractType!{! private $myManager;!! public function __construct(MyManager $manager)! {! $this->myManager = $manager;! }!! public function buildForm(FormBuilderInterface $builder, array $options)! {! $transformer = new MyTransformer($this->manager);! $builder->addModelTransformer($transformer);! }!! public function getParent()! {! return 'text';! }!! public function getName()! {! return 'my_text';! }!}!
![Page 27: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/27.jpg)
Andrea Giuliano @bit_shark
Data transformers
class MeetingType extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $option)! {! $builder->add('name', 'my_text');! $builder->add('when', 'date');! $builder->add('featured', 'checkbox');! }!! public function getName()! {! return 'meeting';! }!}!
use my_text as a standard type
![Page 28: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/28.jpg)
Andrea Giuliano @bit_shark
Remember
Data Transformers transforms data representation
Don’t use them to change data information
![Page 29: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/29.jpg)
Events
![Page 30: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/30.jpg)
Andrea Giuliano @bit_shark
To change data information use form events
Events
![Page 31: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/31.jpg)
Andrea Giuliano @bit_shark
class FacebookSubscriber implements EventSubscriberInterface!{! public static function getSubscribedEvents()! {! return array(FormEvents::PRE_SET_DATA => 'preSetData');! }!! public function preSetData(FormEvent $event)! {! $data = $event->getData();! $form = $event->getForm();!! if (null === $data) {! return;! }!! if (!$data->getFacebookId()) {! $form->add('username');! $form->add('password');! }! }!}
Events
![Page 32: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/32.jpg)
Andrea Giuliano @bit_shark
class RegistrationType extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $options)! {! $builder->add('name');! $builder->add('surname');!! $builder->addEventSubscriber(new FacebookSubscriber());! }!! public function getName()! {! return 'registration';! }!
!...!!
}
Events
add it to your type
![Page 33: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/33.jpg)
Andrea Giuliano @bit_shark
class RegistrationForm extends AbstractType!{! public function buildForm(FormBuilderInterface $builder, array $options)! {! $builder->add('name');! $builder->add('surname');!! $builder->get('surname')->addEventListener(! FormEvents::BIND,! function(FormEvent $event){! $event->setData(ucwords($event->getData()))! }! );! }!! public function getName()! {! return 'registration';! }!}
Events
![Page 34: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/34.jpg)
Andrea Giuliano @bit_shark
PRE_SET_DATA
Events
Model Norm View
$form->setData($symfonyDay);
meeting [Form]
POST_SET_DATA
child
![Page 35: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/35.jpg)
Andrea Giuliano @bit_shark
POST_BIND
Events
Model Norm View
meeting [Form]
child
$form->handleRequest($request);
PRE_BIND
BIND
![Page 36: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/36.jpg)
Test
![Page 37: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/37.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Dnsee\EventBundle\Form\Type\EventType;!use Dnsee\EventBundle\Model\EventObject;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! public function testSubmitValidData()! {! $formData = array(! 'name' => 'SymfonyDay',! 'date' => '2013-10-18',! 'featured' => true,! );!! $type = new TestedType();! $form = $this->factory->create($type);!! $object = new TestObject();! $object->fromArray($formData);!! // submit the data to the form directly! $form->submit($formData);!! $this->assertTrue($form->isSynchronized());! $this->assertEquals($object, $form->getData());!! $view = $form->createView();! $children = $view->children;!! foreach (array_keys($formData) as $key) {! $this->assertArrayHasKey($key, $children);! }! }!}
Test
![Page 38: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/38.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Dnsee\EventBundle\Form\Type\EventType;!use Dnsee\EventBundle\Model\Event;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! public function testSubmitValidData()! {! $formData = array(! 'name' => 'SymfonyDay',! 'when' => '2013-10-18',! 'featured' => true,! );!! $type = new EventType();! $form = $this->factory->create($type);!! $event = new Event();! $event->fromArray($formData);! ! [...]!
Test
decide the data to be submitted
![Page 39: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/39.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Dnsee\EventBundle\Form\Type\EventType;!use Dnsee\EventBundle\Model\EventObject;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! public function testSubmitValidData()! {!! [...]!! $form->submit($formData);!! $this->assertTrue($form->isSynchronized());! $this->assertEquals($object, $form->getData());!! [...]!!
Test
test data transformers
![Page 40: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/40.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Acme\TestBundle\Form\Type\TestedType;!use Acme\TestBundle\Model\TestObject;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! public function testSubmitValidData()! {!!
[...]!!
$view = $form->createView();! $children = $view->children;!! foreach (array_keys($formData) as $key) {! $this->assertArrayHasKey($key, $children);! }! }!}!
Test
test form view creation
![Page 41: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/41.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Dnsee\EventBundle\Form\Type\EventType;!use Dnsee\EventBundle\Model\EventObject;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! protected function getExtensions()! {! $myCustomType = new MyCustomType();! return array(new PreloadedExtension(array(! $myCustomType->getName() => $customType,! ), array()));! }!! public function testSubmitValidData()! {! [...]! }!}
Test
![Page 42: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/42.jpg)
Andrea Giuliano @bit_shark
namespace Acme\TestBundle\Tests\Form\Type;!!use Dnsee\EventBundle\Form\Type\EventType;!use Dnsee\EventBundle\Model\EventObject;!use Symfony\Component\Form\Test\TypeTestCase;!!class MeetingTypeTest extends TypeTestCase!{! protected function getExtensions()! {! $myCustomType = new MyCustomType();! return array(new PreloadedExtension(array(! $myCustomType->getName() => $customType,! ), array()));! }!! public function testSubmitValidData()! {! [...]! }!}
Test
Test your custom type FIRST
![Page 43: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/43.jpg)
?
![Page 45: Everything you always wanted to know about forms* *but were afraid to ask](https://reader033.fdocuments.us/reader033/viewer/2022052121/554a06b2b4c905557a8b5581/html5/thumbnails/45.jpg)
References
https://speakerdeck.com/webmozart/symfony2-form-tricks http://www.flickr.com/photos/yahya/132963781/ http://www.flickr.com/photos/lutherankorean/2694858251/ http://www.flickr.com/photos/lauroroger/8808985531/ http://www.flickr.com/photos/gifake/4643253235/ http://www.flickr.com/photos/zorin-denu/5222189908/ http://www.flickr.com/photos/aigle_dore/10014783623/ http://www.flickr.com/photos/skosoris/4985591296/ http://www.flickr.com/photos/sharynmorrow/248647126/