SlideShare uma empresa Scribd logo
1 de 49
Baixar para ler offline
Symfony
Form component
Plan
1. Basic usage
2. Validation
3. Custom types
4. Events
5. Data Transformers
6. Form type extensions
7. Rendering overview
What's the Form
component?
Basic usages
Basic usage (Symfony way)
public function createAction(Request $request)
{
$form = $this
->createFormBuilder([])
->add('comment', 'textarea')
->getForm()
;
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
// Do what ever you want with the data...
$comment = $data['comment'];
}
return [
'form' => $form->createView(),
];
}
Basic usage (rendering)
# create.html.twig
{{ form_start(form) }}
{{ form_errors(form) }}
{{ form_row(form.comment) }}
<input type="submit" name="Let's go" />
{{ form_end(form) }}
Basic usage (Object instead of array)
public function createOrUpdateAction(Request $request, MyObject $myObject = null)
{
$myObject = $myObject :? new MyObject();
$form = $this
->createFormBuilder($myObject, [
'data_class' => MyObject::class,
])
->add('comment', 'textarea')
->getForm()
;
$form->handleRequest($request);
if ($form->isValid()) {
// Do what ever you want with the updated object...
$comment = $myObject->getComment();
}
return [
'form' => $form->createView(),
];
}
Validation
Validation
$form = $this->createFormBuilder()
->add('comment', 'textarea', [
'required' => true,
'constraints' => [
new NotBlank(),
],
])
->getForm()
;
Basic usage (Validation on the object)
use SymfonyComponentValidatorConstraints as Assert;
class MyObject
{
/**
* @AssertNotBlank
* @AssertLength(
* min=10,
* minMessage="The comment have to be useful"
* )
*/
private $comment;
// Required methods
public function getComment();
public function setComment($comment);
}
Basic usage (Get validation errors)
...that's rendered for you!
But if you want access to them...
$form->handleRequest($request);
if (!$form->isValid()) {
$errors = form->getErrors();
// `$errors` is an array of `FormError` objects.
}
Hey!
31 built-in types
46 built-in validators
Custom types
Custom type definition
class MyFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('comment', 'textarea')
;
}
}
Using the Form Type
public function createAction(Request $request)
{
$form = $this->createForm(new MyFormType());
$form->handleRequest($request);
if ($form->isValid()) {
$data = $form->getData();
// Do what ever you want with the data...
$comment = $data['comment'];
}
return [
'form' => $form->createView(),
];
}
Form Type options
class MyFormType extends AbstractType
{
//! Replace `setDefaultOptions` since Symfony 3.0 /!
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['my-custom-option']);
$resolver->setDefaults(array(
'data_class' => 'AppModelObject',
));
}
}
Form Type as a service
class GenderType extends AbstractType
{
private $genderChoices;
public function __construct(array $genderChoices)
{
$this->genderChoices = $genderChoices;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'choices' => $this->genderChoices,
));
}
}
Form Type as a service
Register the form type
<service id="app.form.type.gender" class="AppFormTypeGenderType">
<argument>%genders%</argument>
<tag name="form.type" />
</service>
Use the form type
class MyFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('gender', GenderType::class)
;
}
}
Events
Or how to dynamically update the FormType based on
data.
Form workflow
It dispatches different events
while handling the requests.
» PRE_SET_DATA
» POST_SET_DATA
» PRE_SUBMIT
» SUBMIT
» POST_SUBMIT
The name field only for a new product
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) {
$product = $event->getData();
$form = $event->getForm();
// The product name is only updatable for a new `Product`
if (!$product || null === $product->getId()) {
$form->add('name', TextType::class);
}
});
}
Event subscribers
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->addEventSubscriber(new AddNameFieldSubscriber());
}
 An event subscriber
class AddNameFieldSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
return array(FormEvents::PRE_SET_DATA => 'preSetData');
}
public function preSetData(FormEvent $event)
{
$product = $event->getData();
$form = $event->getForm();
if (!$product || null === $product->getId()) {
$form->add('name', TextType::class);
}
}
}
List based on another field
1. Initial Form Type
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('sport', EntityType::class, array(
'class' => 'AppBundle:Sport',
'placeholder' => '',
))
;
}
List based on another field
2. Our form modifier
$formModifier = function (FormInterface $form, Sport $sport = null) {
$positions = null === $sport ? array() : $sport->getAvailablePositions();
$form->add('position', EntityType::class, array(
'class' => 'AppBundle:Position',
'placeholder' => '',
'choices' => $positions,
));
};
List based on another field
3. The listeners
$builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) {
$data = $event->getData();
$formModifier($event->getForm(), $data->getSport());
});
$builder->get('sport')->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($formModifier) {
// It's important here to fetch $event->getForm()->getData(), as
// $event->getData() will get you the client data (that is, the ID)
$sport = $event->getForm()->getData();
// since we've added the listener to the child, we'll have to pass on
// the parent to the callback functions!
$formModifier($event->getForm()->getParent(), $sport);
});
Data Transformers
Normalization flow
1. Model data. Our object returned
by getData().
2. Internal representation, mostly
our model data. Almost never
used by the developer.
3. View data. The data structure
sent to submit().
Using the CallbackTransformer
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('description', TextareaType::class);
$builder->get('description')->addModelTransformer(new CallbackTransformer(function ($originalDescription) {
// transform <br/> to n so the textarea reads easier
return preg_replace('#<brs*/?>#i', "n", $originalDescription);
}, function ($submittedDescription) {
// remove most HTML tags (but not br,p)
$cleaned = strip_tags($submittedDescription, '<br><br/><p>');
// transform any n to real <br/>
return str_replace("n", '<br/>', $cleaned);
}));
}
An integer to an object
1. Our task Form Type
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', TextareaType::class)
->add('issue', TextType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppModelTask'
));
}
// ...
}
An integer to an object
2. The transformer
class IssueToNumberTransformer implements DataTransformerInterface
{
private $issueRepository;
public function __construct(IssueRepository $issueRepository) {
$this->issueRepository = $issueRepository;
}
// Two methods to implement...
public function transform($issue);
public function reverseTransform($issueNumber);
}
An integer to an object
3. From model to view
public function transform($issue)
{
return null !== $issue ? $issue->getId() : '';
}
An integer to an object
3. From view to model
public function reverseTransform($issueNumber)
{
if (empty($issueNumber)) {
return;
}
if (null === ($issue = $this->issueRepository->find($issueNumber))) {
throw new TransformationFailedException(sprintf('An issue with number "%s" does not exist!', $issueNumber));
}
return $issue;
}
An integer to an object
4. Voilà!
class TaskType extends AbstractType
{
private $issueRepository;
public function __construct(IssueRepository $issueRepository) {
$this->issueRepository = $issueRepository;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// ...
$builder->get('issue')->addModelTransformer(new IssueToNumberTransformer($this->issueRepository));
}
}
Form Type Extensions
An extension class
class IconTypeExtension extends AbstractTypeExtension
{
public function getExtendedType()
{
return ChoiceType::class;
}
// We can now declare the following methods...
public function configureOptions(OptionsResolver $resolver);
public function buildForm(FormBuilderInterface $builder, array $options);
public function buildView(FormView $view, FormInterface $form, array $options);
public function finishView(FormView $view, FormInterface $form, array $options)
}
An optional extra icon
class IconTypeExtension extends AbstractTypeExtension
{
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'icon' => null,
]);
}
}
An optional extra icon
class IconTypeExtension extends AbstractTypeExtension
{
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['icon'] = $options['icon'];
}
}
You'll need to extend the choice_widget block using a form
theme, so you can display an icon when the local icon variable is
defined.
Register the extension
<service
id="app.image_type_extension"
class="AppFormExtensionImageTypeExtension">
<tag name="form.type_extension"
extended-type="SymfonyComponentFormExtensionCoreTypeChoiceType" />
</service>
 Rendering
Using a form theme
{% form_theme form 'form/fields.html.twig' %}
{# or.. #}
{% form_theme form _self %}
{{ form(form) }}
Example theme
# form/fields.html.twig
{% block form_row %}
{% spaceless %}
<div class="form_row">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %}
Creating a form theme
Using Twig blocks.
» [type]_row
» [type]_widget
» [type]_label
» [type]_errors
If the given block of type is not found, it will use the parent's
type.
FormType's buildView
class GenderType extends AbstractType
{
private $genderChoices;
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->vars['genders'] = $this->genderChoices;
}
}
FormType's buildView
# form/fields.html.twig
{% block gender_widget %}
{% spaceless %}
{# We can use the `gender` variable #}
{% endspaceless %}
{% endblock %}
FormType's finishView
Called when the children's view is completed.
public function finishView(FormView $view, FormInterface $form, array $options)
{
$multipart = false;
foreach ($view->children as $child) {
if ($child->vars['multipart']) {
$multipart = true;
break;
}
}
$view->vars['multipart'] = $multipart;
}
Creating a form without name
1. The difference?
Your form properties won't be namespaced
Example: comment instead of my_form[comment]
You might need/want to use it for:
- Legacy applications compatibility
- APIs (with the FOS Rest Body Listener)
Creating a form without name
2. How?
private $formFactory;
public function __construct(FormFactoryInterface $formFactory)
{
$this->formFactory = $formFactory;
}
public function createAction(Request $request)
{
$form = $this->formFactory->createNamed(null, new MyFormType());
$form->handleRequest($request);
// ...
}
Wow, we're done!

Mais conteúdo relacionado

Mais procurados

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Samuel ROZE
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony AppsKris Wallsmith
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Fabien Potencier
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & RESTHugo Hamon
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixturesBill Chang
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleHugo Hamon
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityRyan Weaver
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonKris Wallsmith
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ EtsyNishan Subedi
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 

Mais procurados (20)

Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)Symfony Messenger (Symfony Live San Francisco)
Symfony Messenger (Symfony Live San Francisco)
 
How Kris Writes Symfony Apps
How Kris Writes Symfony AppsHow Kris Writes Symfony Apps
How Kris Writes Symfony Apps
 
Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)Be RESTful (Symfony Camp 2008)
Be RESTful (Symfony Camp 2008)
 
Matters of State
Matters of StateMatters of State
Matters of State
 
Silex meets SOAP & REST
Silex meets SOAP & RESTSilex meets SOAP & REST
Silex meets SOAP & REST
 
Doctrine fixtures
Doctrine fixturesDoctrine fixtures
Doctrine fixtures
 
Design Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et PimpleDesign Patterns avec PHP 5.3, Symfony et Pimple
Design Patterns avec PHP 5.3, Symfony et Pimple
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Bacbkone js
Bacbkone jsBacbkone js
Bacbkone js
 
Guard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful SecurityGuard Authentication: Powerful, Beautiful Security
Guard Authentication: Powerful, Beautiful Security
 
How kris-writes-symfony-apps-london
How kris-writes-symfony-apps-londonHow kris-writes-symfony-apps-london
How kris-writes-symfony-apps-london
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
Cyclejs introduction
Cyclejs introductionCyclejs introduction
Cyclejs introduction
 
Virtual Madness @ Etsy
Virtual Madness @ EtsyVirtual Madness @ Etsy
Virtual Madness @ Etsy
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 

Destaque

Docker orchestration with Kubernetes
Docker orchestration with KubernetesDocker orchestration with Kubernetes
Docker orchestration with KubernetesSamuel ROZE
 
CoreOS Overview and Current Status
CoreOS Overview and Current StatusCoreOS Overview and Current Status
CoreOS Overview and Current StatusSreenivas Makam
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesSreenivas Makam
 
An Introduction to Kubernetes
An Introduction to KubernetesAn Introduction to Kubernetes
An Introduction to KubernetesImesh Gunaratne
 
Delve into Helm - Advanced DevOps
Delve into Helm - Advanced DevOpsDelve into Helm - Advanced DevOps
Delve into Helm - Advanced DevOpsLachlan Evenson
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheLeslie Samuel
 

Destaque (9)

Docker orchestration with Kubernetes
Docker orchestration with KubernetesDocker orchestration with Kubernetes
Docker orchestration with Kubernetes
 
Docker and Kubernetes
Docker and KubernetesDocker and Kubernetes
Docker and Kubernetes
 
Introduction to Kubernetes
Introduction to KubernetesIntroduction to Kubernetes
Introduction to Kubernetes
 
CoreOS Overview and Current Status
CoreOS Overview and Current StatusCoreOS Overview and Current Status
CoreOS Overview and Current Status
 
Kubernetes Basics
Kubernetes BasicsKubernetes Basics
Kubernetes Basics
 
Service Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and KubernetesService Discovery using etcd, Consul and Kubernetes
Service Discovery using etcd, Consul and Kubernetes
 
An Introduction to Kubernetes
An Introduction to KubernetesAn Introduction to Kubernetes
An Introduction to Kubernetes
 
Delve into Helm - Advanced DevOps
Delve into Helm - Advanced DevOpsDelve into Helm - Advanced DevOps
Delve into Helm - Advanced DevOps
 
How to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your NicheHow to Become a Thought Leader in Your Niche
How to Become a Thought Leader in Your Niche
 

Semelhante a Symfony CoP: Form component

Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with ReactGreeceJS
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askAndrea Giuliano
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hackingJeroen van Dijk
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Arnaud Langlade
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsSam Hennessy
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologyDaniel Knell
 
14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilorRazvan Raducanu, PhD
 
Data20161007
Data20161007Data20161007
Data20161007capegmail
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2eugenio pombi
 
Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Julien Vinber
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumnameEmanuele Quinto
 
Apostrophe
ApostropheApostrophe
Apostrophetompunk
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXDrupalSib
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesŁukasz Chruściel
 

Semelhante a Symfony CoP: Form component (20)

Taming forms with React
Taming forms with ReactTaming forms with React
Taming forms with React
 
Everything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to askEverything you always wanted to know about forms* *but were afraid to ask
Everything you always wanted to know about forms* *but were afraid to ask
 
Symfony tips and tricks
Symfony tips and tricksSymfony tips and tricks
Symfony tips and tricks
 
WordPress REST API hacking
WordPress REST API hackingWordPress REST API hacking
WordPress REST API hacking
 
Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)Code moi une RH! (PHP tour 2017)
Code moi une RH! (PHP tour 2017)
 
Adding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy ApplicationsAdding Dependency Injection to Legacy Applications
Adding Dependency Injection to Legacy Applications
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Symfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technologySymfony2 Building on Alpha / Beta technology
Symfony2 Building on Alpha / Beta technology
 
14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor14. CodeIgniter adaugarea inregistrarilor
14. CodeIgniter adaugarea inregistrarilor
 
Data20161007
Data20161007Data20161007
Data20161007
 
Symfony2. Form and Validation
Symfony2. Form and ValidationSymfony2. Form and Validation
Symfony2. Form and Validation
 
PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2PHPUnit elevato alla Symfony2
PHPUnit elevato alla Symfony2
 
Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?Et si on en finissait avec CRUD ?
Et si on en finissait avec CRUD ?
 
Migrare da symfony 1 a Symfony2
 Migrare da symfony 1 a Symfony2  Migrare da symfony 1 a Symfony2
Migrare da symfony 1 a Symfony2
 
Drupal csu-open atriumname
Drupal csu-open atriumnameDrupal csu-open atriumname
Drupal csu-open atriumname
 
Apostrophe
ApostropheApostrophe
Apostrophe
 
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAXМихаил Крайнюк - Form API + Drupal 8: Form and AJAX
Михаил Крайнюк - Form API + Drupal 8: Form and AJAX
 
Lithium Best
Lithium Best Lithium Best
Lithium Best
 
Unittests für Dummies
Unittests für DummiesUnittests für Dummies
Unittests für Dummies
 
Unveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New FeaturesUnveiling the Future: Sylius 2.0 New Features
Unveiling the Future: Sylius 2.0 New Features
 

Mais de Samuel ROZE

Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Samuel ROZE
 
Living documentation
Living documentationLiving documentation
Living documentationSamuel ROZE
 
Micro services may not be the best idea
Micro services may not be the best ideaMicro services may not be the best idea
Micro services may not be the best ideaSamuel ROZE
 
Take care of our micro services
Take care of our micro servicesTake care of our micro services
Take care of our micro servicesSamuel ROZE
 
(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et ToleranceSamuel ROZE
 
Using continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsUsing continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsSamuel ROZE
 
Behat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatBehat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatSamuel ROZE
 
Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Samuel ROZE
 

Mais de Samuel ROZE (8)

Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)
 
Living documentation
Living documentationLiving documentation
Living documentation
 
Micro services may not be the best idea
Micro services may not be the best ideaMicro services may not be the best idea
Micro services may not be the best idea
 
Take care of our micro services
Take care of our micro servicesTake care of our micro services
Take care of our micro services
 
(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance
 
Using continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsUsing continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflows
 
Behat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatBehat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than that
 
Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer
 

Último

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesVictorSzoltysek
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfVishalKumarJha10
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionOnePlan Solutions
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdfPearlKirahMaeRagusta1
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfryanfarris8
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...OnePlan Solutions
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...software pro Development
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 

Último (20)

AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdfintroduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
introduction-to-automotive Andoid os-csimmonds-ndctechtown-2021.pdf
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdfAzure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
Azure_Native_Qumulo_High_Performance_Compute_Benchmarks.pdf
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
Tech Tuesday-Harness the Power of Effective Resource Planning with OnePlan’s ...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...How to Choose the Right Laravel Development Partner in New York City_compress...
How to Choose the Right Laravel Development Partner in New York City_compress...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 

Symfony CoP: Form component

  • 2. Plan 1. Basic usage 2. Validation 3. Custom types 4. Events 5. Data Transformers 6. Form type extensions 7. Rendering overview
  • 5. Basic usage (Symfony way) public function createAction(Request $request) { $form = $this ->createFormBuilder([]) ->add('comment', 'textarea') ->getForm() ; $form->handleRequest($request); if ($form->isValid()) { $data = $form->getData(); // Do what ever you want with the data... $comment = $data['comment']; } return [ 'form' => $form->createView(), ]; }
  • 6. Basic usage (rendering) # create.html.twig {{ form_start(form) }} {{ form_errors(form) }} {{ form_row(form.comment) }} <input type="submit" name="Let's go" /> {{ form_end(form) }}
  • 7. Basic usage (Object instead of array) public function createOrUpdateAction(Request $request, MyObject $myObject = null) { $myObject = $myObject :? new MyObject(); $form = $this ->createFormBuilder($myObject, [ 'data_class' => MyObject::class, ]) ->add('comment', 'textarea') ->getForm() ; $form->handleRequest($request); if ($form->isValid()) { // Do what ever you want with the updated object... $comment = $myObject->getComment(); } return [ 'form' => $form->createView(), ]; }
  • 9. Validation $form = $this->createFormBuilder() ->add('comment', 'textarea', [ 'required' => true, 'constraints' => [ new NotBlank(), ], ]) ->getForm() ;
  • 10. Basic usage (Validation on the object) use SymfonyComponentValidatorConstraints as Assert; class MyObject { /** * @AssertNotBlank * @AssertLength( * min=10, * minMessage="The comment have to be useful" * ) */ private $comment; // Required methods public function getComment(); public function setComment($comment); }
  • 11. Basic usage (Get validation errors) ...that's rendered for you! But if you want access to them... $form->handleRequest($request); if (!$form->isValid()) { $errors = form->getErrors(); // `$errors` is an array of `FormError` objects. }
  • 12. Hey! 31 built-in types 46 built-in validators
  • 14. Custom type definition class MyFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('comment', 'textarea') ; } }
  • 15. Using the Form Type public function createAction(Request $request) { $form = $this->createForm(new MyFormType()); $form->handleRequest($request); if ($form->isValid()) { $data = $form->getData(); // Do what ever you want with the data... $comment = $data['comment']; } return [ 'form' => $form->createView(), ]; }
  • 16. Form Type options class MyFormType extends AbstractType { //! Replace `setDefaultOptions` since Symfony 3.0 /! public function configureOptions(OptionsResolver $resolver) { $resolver->setRequired(['my-custom-option']); $resolver->setDefaults(array( 'data_class' => 'AppModelObject', )); } }
  • 17. Form Type as a service class GenderType extends AbstractType { private $genderChoices; public function __construct(array $genderChoices) { $this->genderChoices = $genderChoices; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'choices' => $this->genderChoices, )); } }
  • 18. Form Type as a service Register the form type <service id="app.form.type.gender" class="AppFormTypeGenderType"> <argument>%genders%</argument> <tag name="form.type" /> </service> Use the form type class MyFormType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('gender', GenderType::class) ; } }
  • 19. Events Or how to dynamically update the FormType based on data.
  • 20. Form workflow It dispatches different events while handling the requests. » PRE_SET_DATA » POST_SET_DATA » PRE_SUBMIT » SUBMIT » POST_SUBMIT
  • 21. The name field only for a new product public function buildForm(FormBuilderInterface $builder, array $options) { // ... $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) { $product = $event->getData(); $form = $event->getForm(); // The product name is only updatable for a new `Product` if (!$product || null === $product->getId()) { $form->add('name', TextType::class); } }); }
  • 22. Event subscribers public function buildForm(FormBuilderInterface $builder, array $options) { // ... $builder->addEventSubscriber(new AddNameFieldSubscriber()); }
  • 23.  An event subscriber class AddNameFieldSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { return array(FormEvents::PRE_SET_DATA => 'preSetData'); } public function preSetData(FormEvent $event) { $product = $event->getData(); $form = $event->getForm(); if (!$product || null === $product->getId()) { $form->add('name', TextType::class); } } }
  • 24. List based on another field 1. Initial Form Type public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('sport', EntityType::class, array( 'class' => 'AppBundle:Sport', 'placeholder' => '', )) ; }
  • 25. List based on another field 2. Our form modifier $formModifier = function (FormInterface $form, Sport $sport = null) { $positions = null === $sport ? array() : $sport->getAvailablePositions(); $form->add('position', EntityType::class, array( 'class' => 'AppBundle:Position', 'placeholder' => '', 'choices' => $positions, )); };
  • 26. List based on another field 3. The listeners $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formModifier) { $data = $event->getData(); $formModifier($event->getForm(), $data->getSport()); }); $builder->get('sport')->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($formModifier) { // It's important here to fetch $event->getForm()->getData(), as // $event->getData() will get you the client data (that is, the ID) $sport = $event->getForm()->getData(); // since we've added the listener to the child, we'll have to pass on // the parent to the callback functions! $formModifier($event->getForm()->getParent(), $sport); });
  • 28. Normalization flow 1. Model data. Our object returned by getData(). 2. Internal representation, mostly our model data. Almost never used by the developer. 3. View data. The data structure sent to submit().
  • 29. Using the CallbackTransformer public function buildForm(FormBuilderInterface $builder, array $options) { $builder->add('description', TextareaType::class); $builder->get('description')->addModelTransformer(new CallbackTransformer(function ($originalDescription) { // transform <br/> to n so the textarea reads easier return preg_replace('#<brs*/?>#i', "n", $originalDescription); }, function ($submittedDescription) { // remove most HTML tags (but not br,p) $cleaned = strip_tags($submittedDescription, '<br><br/><p>'); // transform any n to real <br/> return str_replace("n", '<br/>', $cleaned); })); }
  • 30. An integer to an object 1. Our task Form Type class TaskType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('description', TextareaType::class) ->add('issue', TextType::class) ; } public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( 'data_class' => 'AppModelTask' )); } // ... }
  • 31. An integer to an object 2. The transformer class IssueToNumberTransformer implements DataTransformerInterface { private $issueRepository; public function __construct(IssueRepository $issueRepository) { $this->issueRepository = $issueRepository; } // Two methods to implement... public function transform($issue); public function reverseTransform($issueNumber); }
  • 32. An integer to an object 3. From model to view public function transform($issue) { return null !== $issue ? $issue->getId() : ''; }
  • 33. An integer to an object 3. From view to model public function reverseTransform($issueNumber) { if (empty($issueNumber)) { return; } if (null === ($issue = $this->issueRepository->find($issueNumber))) { throw new TransformationFailedException(sprintf('An issue with number "%s" does not exist!', $issueNumber)); } return $issue; }
  • 34. An integer to an object 4. Voilà! class TaskType extends AbstractType { private $issueRepository; public function __construct(IssueRepository $issueRepository) { $this->issueRepository = $issueRepository; } public function buildForm(FormBuilderInterface $builder, array $options) { // ... $builder->get('issue')->addModelTransformer(new IssueToNumberTransformer($this->issueRepository)); } }
  • 36. An extension class class IconTypeExtension extends AbstractTypeExtension { public function getExtendedType() { return ChoiceType::class; } // We can now declare the following methods... public function configureOptions(OptionsResolver $resolver); public function buildForm(FormBuilderInterface $builder, array $options); public function buildView(FormView $view, FormInterface $form, array $options); public function finishView(FormView $view, FormInterface $form, array $options) }
  • 37. An optional extra icon class IconTypeExtension extends AbstractTypeExtension { public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ 'icon' => null, ]); } }
  • 38. An optional extra icon class IconTypeExtension extends AbstractTypeExtension { public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['icon'] = $options['icon']; } } You'll need to extend the choice_widget block using a form theme, so you can display an icon when the local icon variable is defined.
  • 39. Register the extension <service id="app.image_type_extension" class="AppFormExtensionImageTypeExtension"> <tag name="form.type_extension" extended-type="SymfonyComponentFormExtensionCoreTypeChoiceType" /> </service>
  • 41. Using a form theme {% form_theme form 'form/fields.html.twig' %} {# or.. #} {% form_theme form _self %} {{ form(form) }}
  • 42. Example theme # form/fields.html.twig {% block form_row %} {% spaceless %} <div class="form_row"> {{ form_label(form) }} {{ form_errors(form) }} {{ form_widget(form) }} </div> {% endspaceless %} {% endblock form_row %}
  • 43. Creating a form theme Using Twig blocks. » [type]_row » [type]_widget » [type]_label » [type]_errors If the given block of type is not found, it will use the parent's type.
  • 44. FormType's buildView class GenderType extends AbstractType { private $genderChoices; public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['genders'] = $this->genderChoices; } }
  • 45. FormType's buildView # form/fields.html.twig {% block gender_widget %} {% spaceless %} {# We can use the `gender` variable #} {% endspaceless %} {% endblock %}
  • 46. FormType's finishView Called when the children's view is completed. public function finishView(FormView $view, FormInterface $form, array $options) { $multipart = false; foreach ($view->children as $child) { if ($child->vars['multipart']) { $multipart = true; break; } } $view->vars['multipart'] = $multipart; }
  • 47. Creating a form without name 1. The difference? Your form properties won't be namespaced Example: comment instead of my_form[comment] You might need/want to use it for: - Legacy applications compatibility - APIs (with the FOS Rest Body Listener)
  • 48. Creating a form without name 2. How? private $formFactory; public function __construct(FormFactoryInterface $formFactory) { $this->formFactory = $formFactory; } public function createAction(Request $request) { $form = $this->formFactory->createNamed(null, new MyFormType()); $form->handleRequest($request); // ... }