the symfony form component from a drupal … symfony form component from a drupal perspective...

107
The Symfony Form Component The Symfony Form Component from a Drupal perspective from a Drupal perspective http://www.flickr.com/photos/dexxus/3146028811/

Upload: vanthien

Post on 25-May-2018

308 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

The Symfony Form ComponentThe Symfony Form Componentfrom a Drupal perspectivefrom a Drupal perspective

http://www.flickr.com/photos/dexxus/3146028811/

Page 2: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 2/107

Outline

● Basic form handling● Data transformation● Data mapping● Validation● Theming● Architecture● What does Drupal's Form API have that Symfony's doesn't?

Page 3: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 3/107

Today's Example

Page 4: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 4/107

Basic Form Handling

http://www.flickr.com/photos/teegardin/5512347305/

Basic Form Handling

Page 5: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 5/107

function my_employee_form(&$form_state) { $form['name'] = array( '#type' => 'textfield', ); $form['salary'] = array( '#type' => 'textfield', ); $form['birth_date'] = array( '#type' => 'date', ); return $form;}

Form Definition

Page 6: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 6/107

$form = $formFactory->createBuilder() ->add('name', 'text') ->add('salary', 'money') ->add('birth_date', 'date') ->getForm();

Form Definition

Page 7: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 7/107

function my_new_employee() { return drupal_get_form('my_employee_form');}

function my_employee_form_submit($form, &$form_state) { $values = $form_state['values']; // ...}

Handling Submitted Forms

Page 8: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 8/107

if ('POST' === $request->getMethod()) { $form->bind($request); if ($form->isValid()) { $values = $form->getData(); // ... }}

Handling Submitted Forms

Page 9: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 9/107

if ('POST' === $request->getMethod()) { $form->bind($request);

if (isset($_POST[$form->getName()])) { $form->bind($_POST[$form->getName()]); if ($form->isValid()) { // ... }}

... without HttpFoundation

Page 10: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 10/107

$html = drupal_get_form('my_employee_form');

Form Rendering

Page 11: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 11/107

$html = $twig->render('new_employee.html', array( 'form' => $form->createView(),));

<form action="#" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /></form>

Form Rendering

Page 12: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 12/107

$form = $formFactory->createBuilder() ->add('name', 'text') ->add('salary', 'money') ->add('birth_date', 'date') ->getForm();

if ('POST' === $request->getMethod()) { $form->bind($request); if ($form->isValid()) { // ... }}

$html = $twig->render('new_employee.html', array( 'form' => $form->createView(),));

Complete Controller Code

Page 13: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 13/107http://www.flickr.com/photos/jessica_digiacomo/5108323683/

Data Transformation

Page 14: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 14/107

View Format

Model Format $empl->getSalary();

Page 15: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 15/107

Example 1: Money Fields

Page 16: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 16/107

$form['salary'] = array( '#type' => 'textfield',);

function my_employee_form_submit($form, &$form_state) { print_r($form_state['values']['salary']);}

Example 1: Money Fields

40000,00

Page 17: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 17/107

$builder->add('salary', 'money');

print_r($form->get('salary')->getData());

Example 1: Money Fields

40000.00

Page 18: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 18/107

$builder->add('salary', 'money', array( 'divisor' => 100,));

print_r($form->get('salary')->getData());

Data Type Configuration

4000000

Page 19: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 19/107

Example 2: Date Fields

Page 20: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 20/107

$form['birth_date'] = array( '#type' => 'date',);

function my_employee_form_submit($form, &$form_state) { print_r($form_state['values']['birth_date']);}

Example 2: Date Fields

Array( [year] => 2012 [month] => 8 [day] => 17)

Page 21: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 21/107

$builder->add('birth_date', 'date');

print_r($form->get('birth_date')->getData());

Example 2: Date Fields

DateTime Object( [date] => 2012-08-17 00:00:00 [timezone_type] => 3 [timezone] => Europe/Vienna)

Page 22: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 22/107

$builder->add('birth_date', 'date', array( 'view_timezone' => 'America/New_York',));

print_r($form->get('birth_date')->getData());

Timezone Configuration

DateTime Object( [date] => 2012-08-17 06:00:00 [timezone_type] => 3 [timezone] => Europe/Vienna)

Page 23: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 23/107

$builder->add('birth_date', 'date', array( 'view_timezone' => 'America/New_York', 'model_timezone' => 'UTC',));

print_r($form->get('birth_date')->getData());

Timezone Configuration

DateTime Object( [date] => 2012-08-17 04:00:00 [timezone_type] => 3 [timezone] => UTC)

Page 24: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 24/107

$builder->add('birth_date', 'date', array( 'input' => 'array',));

print_r($form->get('birth_date')->getData());

Data Type Configuration

Array( [year] => 2012 [month] => 8 [day] => 17)

Page 25: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 25/107

$builder->add('birth_date', 'date', array( 'input' => 'timestamp',));

print_r($form->get('birth_date')->getData());

Data Type Configuration

1345154400

Page 26: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 26/107

$builder->add('birth_date', 'date', array( 'input' => 'string',));

print_r($form->get('birth_date')->getData());

Data Type Configuration

2012-08-17

Page 27: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 27/107

$builder->add('birth_date', 'date');

Configuring the Rendering

Page 28: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 28/107

$builder->add('birth_date', 'date', array( 'widget' => 'single_text',));

Configuring the Rendering

Page 29: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 29/107

$builder->add('birth_date', 'date', array( 'widget' => 'text',));

Configuring the Rendering

Page 30: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 30/107

$builder->add('team', 'entity', array( 'class' => 'Webmozart\Team',));

print_r($form->get('team')->getData());

Example 3: Entity Fields (Single Selection)

Webmozart\Team Object()

Page 31: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 31/107

$builder->add('team', 'entity', array( 'class' => 'Webmozart\Team',));

print_r($form->get('team')->getData());

Example 3: Entity Fields (Multi-Selection)

Doctrine\Common\Collections\ArrayCollection Object( [_elements:Doctrine\...\ArrayCollection:private] => Array ( [0] => Webmozart\Team Object [1] => Webmozart\Team Object

Page 32: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 32/107http://www.flickr.com/photos/freefoto/5982549938/

How it works

Page 33: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 33/107

Data Transformation

● Converts data between different representations● Bijective function

Page 34: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 34/107

Data Transformation

Page 35: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 35/107

Data Transformation

Page 36: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 36/107http://www.flickr.com/photos/wvs/701772889/

Data Mapping

Page 37: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 37/107

Prepopulation with Default Values$form['name'] = array( '#type' => 'textfield', '#default_value' => $employee->getName(),);$form['salary'] = array( '#type' => 'textfield', '#default_value' => $employee->getSalary(),);$form['birth_date'] = array( '#type' => 'date', '#default_value' => array( 'year' => $employee->getBirthDate()->format('y'), 'month' => $employee->getBirthDate()->format('M'), 'day' => $employee->getBirthDate()->format('d'), ));

Page 38: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 38/107

Prepopulation with Default Values

$defaults = array( 'name' => $employee->getBirthDate(), 'salary' => $employee->getSalary(), 'birth_date' => $employee->getBirthDate(),);

$form = $formFactory->createBuilder('form', $defaults) ->add('name', 'text') ->add('salary', 'money') ->add('birth_date', 'date') ->getForm();

Page 39: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 39/107

Prepopulation with Default Values

$form = $formFactory->createBuilder() ->add('name', 'text', array( 'data' => $employee->getName(), )) ->add('salary', 'money', array( 'data' => $employee->getSalary(), )) ->add('birth_date', 'date', array( 'data' => $employee->getBirthDate(), )) ->getForm();

Page 40: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 40/107

Prepopulation with Default Values

$opts = array('data_class' => 'Webmozart\Employee');

$form = $formFactory->createBuilder('form', $empl, $opts) ->add('name', 'text') ->add('salary', 'money') ->add('birthDate', 'date') ->getForm();

Page 41: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 41/107

Reading Submitted Values

function my_employee_form_submit($form, &$form_state) { $values = $form_state['values']; // ...}

Page 42: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 42/107

Reading Submitted Values

$form->bind($request);

if ($form->isValid()) { $values = $form->getData(); // ...}

Page 43: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 43/107

Reading Submitted Values

$form->bind($request);

if ($form->isValid()) { $employeeNo = $form->get('name')->getData(); $salary = $form->get('salary')->getData(); $birthDate = $form->get('birth_date')->getData(); // ...}

Page 44: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 44/107

Reading Submitted Values$opts = array('data_class' => 'Webmozart\Employee');

$form = $formFactory->createBuilder('form', $empl, $opts) // ... ->getForm(); $form->bind($request);

if ($form->isValid()) { $empl->getName(); $empl->getSalary(); // ...}

Page 45: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 45/107http://www.flickr.com/photos/freefoto/5982549938/

How it works

Page 46: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 46/107

Data Mapper

● Distributes a form's data to its children● and back

Page 47: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 47/107

Prepopulation with Default Values

Page 48: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 48/107

Update with Submitted Values

Page 49: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 49/107

Unmapped Fields

$form = $formFactory->createBuilder('form', $empl, $opts) ->add('name', 'text') ->add('salary', 'money') ->add('birthDate', 'date') ->add('termsAccepted', 'checkbox', array( 'mapped' => false, 'data' => false, )) ->getForm();

Page 50: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 50/107

Custom Property Mapping

Page 51: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 51/107

Custom Property Mapping

$form = $formFactory->createBuilder('form', $empl, $opts) ->add('name', 'text') ->add('salary', 'money') ->add('birthDate', 'date', array( 'property_path' => 'personalData.birthDate', )) ->getForm();

Page 52: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 52/107

Validation

http://www.flickr.com/photos/karamell/4612302824/

Page 53: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 53/107

Field Validation

$form['name'] = array( '#type' => 'textfield', '#element_validate' => 'validate_min_length',);

function validate_min_length($element, &$form_state) { if (strlen($element['#value']) < 4)) { form_error($element, t( 'This field should contain at least four ' . 'characters' )); }}

Page 54: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 54/107

Field Validation

$builder->add('name', 'text', array( 'constraints' => new Callback( function ($value, ExecutionContext $context) { if (strlen($value) < 4) { $context->addViolation( 'This field should contain at ' . 'least four characters' ); } } ),));

Page 55: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 55/107

Field Validation

$builder->add('name', 'text', array( 'constraints' => new MinLength(4),));

Page 56: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 56/107

Required vs. Not Required

$form['name'] = array( '#type' => 'textfield', '#required' => true,);

Page 57: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 57/107

Required vs. Not Required

$builder->add('name', 'text', array( 'constraints' => new NotBlank(), 'required' => true,));

Page 58: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 58/107

Validating Multiple Fields

function my_employee_form_validate($form, &$form_state) { if ($form_state['values']['email'] !== $form_state['values']['email_confirm']) { form_set_error('email_confirm', t( 'The email addresses do not match' )); }}

Page 59: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 59/107

Validating Multiple Fields$opts = array( 'constraints' => new Callback( function ($values, ExecutionContext $context) { if ($values['email'] !== $values['email_confirm']) { $context->addViolationAtSubPath( '[email_confirm]', 'The email addresses do not match' ); } } ),);

$form = $formFactory->createBuilder('form', null, $opts) ->add(/* ... */) ->getForm();

Page 60: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 60/107

Limited Validation

$form['actions']['previous'] = array( '#type' => 'submit', '#limit_validation_errors' => array( array('step1'), array('foo', 'bar'), ),);

Page 61: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 61/107

Limited Validation$opts = array( 'validation_groups' => 'Step1',);

$form = $formFactory->createBuilder('form', null, $opts) ->add('name', 'text', array( 'constraints' => array( new NotBlank(array('groups' => 'Step1')), new MinLength(array('limit' => 4, 'groups' => 'Step1')), ), )) ->add('birth_date', 'date', array( 'constraints' => new NotBlank(array('groups' => 'Step2')), )) ->getForm();

Page 62: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 62/107

Limited Validationclass Employee{ /** * @NotBlank * @MinLength(4, message = "The name should contain four characters * or more") */ private $employeeNo; /** * @NotBlank(groups = "Step1") */ private $salary; /** * @NotBlank(groups = "Step2") */ private $birthDate;}

Page 63: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 63/107

Using the Symfony2 Validator

$violations = $validator->validate($form);

$violations = $validator->validate($employee);

$violations = $validator->validateValue( $value, new MinLength(4));

Page 64: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 64/107

Theming

http://www.flickr.com/photos/pagedooley/4176075327/

Page 65: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 65/107

Form Rendering

$html = drupal_get_form('my_employee_form');

Page 66: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 66/107

Form Rendering

$html = $twig->render('new_employee.html', array( 'form' => $form->createView(),));

<form action="#" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /></form>

Page 67: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 67/107

Form Rendering

<form action="#" method="post" {{ form_enctype(form) }}> {{ form_row(form.name) }} {{ form_row(form.salary) }} {{ form_row(form.birth_date) }} {{ form_rest(form) }} <input type="submit" /></form>

Page 68: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 68/107

Form Rendering

<form action="#" method="post" {{ form_enctype(form) }}> <div> {{ form_label(form.name) }} {{ form_errors(form.name) }} {{ form_widget(form.name) }} </div> {{ form_row(form.salary) }} {{ form_row(form.birth_date) }} {{ form_rest(form) }} <input type="submit" /></form>

Page 69: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 69/107

Form Rendering

<form action="#" method="post" {{ form_enctype(form) }}> <div> <label for="{{ form.name.vars.id }}"> {{ form.name.vars.label }} </label> {{ form_errors(form.name) }} {{ form_widget(form.name) }} </div> {{ form_row(form.salary) }} {{ form_row(form.birth_date) }} {{ form_rest(form) }} <input type="submit" /></form>

Page 70: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 70/107

Styling Individual Fields

$form['name'] = array( '#type' => 'textfield', '#prefix' => '<div class="name">', '#suffix' => '</div>',);

Page 71: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 71/107

Styling Individual Fields

{% block _form_name_widget %} <div class="name">{{ form_widget(form) }}</div>{% endblock %}

<form action="#" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <input type="submit" /></form>

Page 72: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 72/107

Label Customization

{% block form_label %} <span class="label"> {{ form_label(form) }} </span>{% endblock %}

Page 73: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 73/107

Label Customization

{% block checkbox_label %} <span class="checkbox-label"> {{ form_label(form) }} </span>{% endblock %}

Page 74: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 74/107

Form Types

Page 75: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 75/107

Form Types

● reusable form definitions● motivation:

● separating form definitions from the controller● creating reusable fields

Page 76: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 76/107

Stripping Down the Controller Code

$opts = array( 'validation_groups' => 'Step1',);

$form = $formFactory->createBuilder('form', null, $opts) ->add('name', 'text') ->add('salary', 'money') ->add('birth_date', 'date') ->getForm();

Page 77: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 77/107

Creating a Custom Form Type

class EmployeeType extends AbstractType{ public function getName() public function setDefaultOptions(OptionsResolverInterface $resolver) public function buildForm(FormBuilderInterface $builder, array $options)}

Page 78: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 78/107

Creating a Custom Form Type

public function getName(){ return 'employee';}

Page 79: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 79/107

public function setDefaultOptions( OptionsResolverInterface $resolver){ $resolver->setDefaults(array( 'validation_groups' => 'Step1', ));}

Creating a Custom Form Type

Page 80: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 80/107

public function buildForm( FormBuilderInterface $builder, array $options){ $builder ->add('name', 'text') ->add('salary', 'money') ->add('birth_date', 'date') ;}

Creating a Custom Form Type

Page 81: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 81/107

$formFactory = Forms::createFormFactoryBuilder() ->addType(new EmployeeType()) ->getFormFactory(); $form = $formFactory->create('employee');

Using the Custom Type

Page 82: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 82/107

Creating a Custom Field

Page 83: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 83/107

$builder->add('team', 'select_or_add', array( 'choices' => array( 'Team 1' => 'Team 1', 'Team 2' => 'Team 2', 'Team 3' => 'Team 3', ),));

Creating a Custom Field

Page 84: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 84/107

class SelectOrAddType extends AbstractType{ public function getName() public function setDefaultOptions(OptionsResolverInterface $resolver) public function buildForm(FormBuilderInterface $builder, array $options)}

Creating a Custom Field

Page 85: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 85/107

public function getName(){ return 'select_or_add';}

Creating a Custom Field

Page 86: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 86/107

public function getName(){ return 'select_or_add';}

Creating a Custom Field

Page 87: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 87/107

public function setDefaultOptions(OptionsResolverInterface $resolver){ $resolver->setRequired(array('choices')); $resolver->setAllowedTypes(array('choices' => 'array'));}

Creating a Custom Field

Page 88: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 88/107

public function buildForm(FormBuilderInterface $builder, array $options){ $builder ->add('choice', 'choice', array( 'choices' => $opts['choices'] + array('Other' => 'Other'), )) ->add('text', 'text', array( 'required' => false, )) ->addModelTransformer( new ValueToChoiceOrTextTransformer($opts['choices']) ) ;}

Creating a Custom Field

Page 89: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 89/107

class ValueToChoiceOrTextTransformer implements DataTransformerInterface{ private $choices;

public function __construct(array $choices) { $this->choices = $choices; }

public function transform($data)

public function reverseTransform($data)}

Creating a Custom Field

Page 90: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 90/107

public function transform($data){ if (in_array($data, $this->choices, true)) { return array('choice' => $data, 'text' => null); }

return array('choice' => 'Other', 'text' => $data);}

Creating a Custom Field

Page 91: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 91/107

public function reverseTransform($data){ if ('Other' === $data['choice']) { return $data['text']; }

return $data['choice'];}

Creating a Custom Field

Page 92: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 92/107

function my_employee_form_alter(&$form, &$form_state, $form_id) { $form['certify'] = array( '#type' => 'checkbox', '#name' => t('I certify that this is my true name'), );}

Modifying Existing Forms

Page 93: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 93/107

class EmployeeTypeCertifyExtension extends AbstractType{ public function getExtendedType() public function buildForm(FormBuilderInterface $builder, array $options)}

Creating a Form Type Extension

Page 94: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 94/107

public function getExtendedType(){ return 'employee';}

Creating a Form Type Extension

Page 95: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 95/107

public function buildForm( FormBuilderInterface $builder, array $options){ $builder->add('certify', 'checkbox', array( 'label' => 'I certify that this is my true name', ));}

Creating a Form Type Extension

Page 96: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 96/107

$formFactory = Forms::createFormFactoryBuilder() ->addType(new EmployeeType()) ->addTypeExtension(new EmployeeTypeCertifyExtension()) ->getFormFactory(); $form = $formFactory->create('employee');

Using a Form Type Extension

Page 97: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 97/107

Architecture

Page 98: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 98/107

High-Level Architecture

Page 99: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 99/107

Low-Level Architecture

Page 100: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 100/107

Low-Level Architecture

Page 101: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 101/107

Events

● Allow dynamic extension of a form● Event with a specific name is fired

● FormEvents::PRE_SET_DATA● FormEvents::POST_SET_DATA● FormEvents::BIND● etc.

● Event listeners observe the event and hook their functionality

Page 102: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 102/107

Events

Page 103: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 103/107

Events

Page 104: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 104/107

What does Drupal's Form API have that Symfony's doesn't?

Page 105: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 105/107

Drupal has it, Symfony2's core doesn't

● fieldset (probably will be added to core)● machine_name● managed_file (probably will be added to core)● tableselect● text_format● vertical_tabs● weight

Page 106: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 106/107

Drupal has it, Symfony2's core doesn't

● button (use Twig instead)● container (use Twig instead)● image_button (use Twig instead)● submit (use Twig instead)● markup (use Twig instead)● item (use Twig instead)

Page 107: The Symfony Form Component from a Drupal … Symfony Form Component from a Drupal perspective Bernhard Schussek @webmozart 2/107 Outline Basic form handling Data transformation Data

Bernhard Schussek @webmozart 107/107

EOF

Bernhard Schussek@webmozart