The new form framework

13,118 views

Published on

Published in: Technology
4 Comments
17 Likes
Statistics
Notes
No Downloads
Views
Total views
13,118
On SlideShare
0
From Embeds
0
Number of Embeds
2,672
Actions
Shares
0
Downloads
163
Comments
4
Likes
17
Embeds 0
No embeds

No notes for slide

The new form framework

  1. 1. The new form framework Bernhard Schussek
  2. 2. What is different in the new form framework?
  3. 3. symfony 1.x User sfForm Controller Domain Model
  4. 4. symfony 1.x User sfForm Business Logic Controller Domain Model
  5. 5. symfony 1.x User sfForm Business Logic Controller Domain Model unit testable!!
  6. 6. symfony 1.x User function configure() { unset($this['foo']); sfFormDoctrine / sfFormPropel unset($this['bar']); unset($this['moo']); unset($this['comeon!']); ... Domain Model
  7. 7. New architecture
  8. 8. Simplicity and Reusability
  9. 9. Embrace your domain model
  10. 10. Symfony 2 User Form Domain Model
  11. 11. Symfony 2 User Presentation Form Domain Model Business Logic designed by you™
  12. 12. Business Logic class Customer { public $name = 'Default'; public getGender(); public setGender($gender); }
  13. 13. Business Logic Presentation class Customer Form { TextField public $name = 'Default'; public getGender(); ChoiceField public setGender($gender); }
  14. 14. $form = new Form('customer', $customer, ...); $form->add(new TextField('name')); $form->add(new ChoiceField('gender', array( 'choices' => array('male', 'female'), )));
  15. 15. $form = new Form('customer', $customer, ...); ... if (isset($_POST['customer'])) { $form->bind($_POST['customer']); }
  16. 16. Business Logic Presentation class Customer Form { to-one relations FieldGroup public $address; }
  17. 17. $group = new FieldGroup('address'); $group->add(...); $group->add(...); $group->add(...); $form->add($group);
  18. 18. Business Logic Presentation class Customer Form { CollectionField to-many relations FieldGroup public $emails; FieldGroup }
  19. 19. $group = new FieldGroup('emails'); $group->add(...); $group->add(...); $form->add(new CollectionField($group));
  20. 20. Default Localized TextField NumberField TimeField TextareaField IntegerField DateTimeField CheckboxField PercentField TimezoneField ChoiceField MoneyField RepeatedField PasswordField DateField CollectionField HiddenField BirthdayField FieldGroup Special
  21. 21. ● Field groups — light-weight subforms — compose other fields or field groups ? DateField ChoiceField ChoiceField CheckboxField CheckboxField
  22. 22. Form Rendering
  23. 23. <?php echo $form->renderFormTag('url') ?> <?php echo $form->renderErrors() ?> <?php echo $form->render() ?> <input type="submit" value="Submit" /> </form>
  24. 24. <label for="<?php echo $form['name']->getId() ?>"> Enter a name </label> <?php echo $form['name']->renderErrors() ?> <?php echo $form['name']->render() ?>
  25. 25. <?php echo $form['date']['day']->render() ?> <?php echo $form['date']['month']->render() ?> <?php echo $form['date']['year']->render() ?>
  26. 26. Validation
  27. 27. symfony 1.x sfForm sfValidator Controller Domain Model Doctrine_Validator
  28. 28. symfony 1.x sfForm sfValidator Controller Duplicate validation logic Domain Model Doctrine_Validator Failed validation leads to 505 errors
  29. 29. Symfony 2 Form Domain Model
  30. 30. Symfony 2 Form Validator Domain Model
  31. 31. Symfony 2 Form Validator Domain Model Validation Metadata "how shall the domain model be validated?"
  32. 32. Customer: properties: name: - MinLength: 6 birthday: - Date: ~ gender: - Choice: [male, female]
  33. 33. <class name="Customer"> <property name="name"> <constraint name="MinLength">6</constraint> </property> <property name="birthday"> <constraint name="Date" /> </property> <property name="gender"> <constraint name="Choice"> <value>male</value> <value>female</value> </constraint> </property> </class>
  34. 34. class Customer { /** @Validation({ @MinLength(6) }) */ public $name; /** @Validation({ @Choice({"male", "female"}) }) */ public function getGender(); /** @Validation({ @Valid }) */ public $gender; }
  35. 35. Type Check String Other AssertTrue AssertType MinLength Min AssertFalse Date MaxLength Max Blank DateTime Regex Choice NotBlank Time Url Valid Null Email Collection NotNull File
  36. 36. ● Constraints can be put on — Classes — Properties — Methods with a "get" or "is" prefix
  37. 37. $validator = $container->getService('validator'); $validator->validate($customer);
  38. 38. Independent from Symfony 2 Zend Doctrine 2 Propel
  39. 39. How does all this fit into the form framework?
  40. 40. $form = new Form('customer', $customer, $this->container->getService('validator'));
  41. 41. $form->bind($_POST['customer']); if ($form->isValid()) { // do something with $customer }
  42. 42. ● The validation is launched automatically upon submission
  43. 43. Common Questions
  44. 44. Q: What if my form does not translate 1:1 to a domain model?
  45. 45. A: Then the domain model doesn't exist yet ;-)
  46. 46. ● Use Case — Extend our form for a checkbox to accept terms and conditions — Should not be stored as field in the Customer class
  47. 47. class Registration { /** @Validation({ @Valid }) */ public $customer; /** * @Validation({ * @AssertTrue(message="Please accept") * }) */ public $termsAccepted = false; public function process() { // save $customer, send emails etc. } }
  48. 48. $form->add(new CheckboxField('termsAccepted')); $group = new FieldGroup('customer'); $group->add(new TextField('name')); ... $form->add($group);
  49. 49. if ($form->isValid()) { $registration->process(); }
  50. 50. ● The Registration class — can be reused (XML requests, …) — can be unit tested
  51. 51. Q: What if I don't want to validate all attributes of an object?
  52. 52. A: Use Constraint groups
  53. 53. ● Use Case — Administrators should be able to create Customers with empty names — Normal users not
  54. 54. class Customer { /** * @Validation({ * @NotBlank(groups="User") * }) */ public $name; ... }
  55. 55. $validator->validate($customer, 'User');
  56. 56. $form->setValidationGroups('User'); $form->bind($_POST('customer')); if ($form->isValid()) { ... }
  57. 57. ● Constraint groups can be sequenced — first validate group "Fast" — then, if "Fast" was valid, validate group "Slow"
  58. 58. Questions?

×