forms - isvalid - Cómo combinar 2 formularios en Symfony2
symfony form validation (3)
Intento crear un foro muy simple con Symfony2.
Mis entidades son: ForumCategory (nombre, descripción ...) ForumTopic (category_id, title) ForumPost (isFirstPost, body, topic_id, author_id ...)
Cuando un usuario intenta crear un tema, quiero mostrar solo un formulario en la misma página para crear un tema y el primer mensaje de la publicación. Me gusta:
- Insertar título del tema: ...
- Insertar cuerpo del tema (cuerpo del mensaje relacionado): ...
[...]
¿Cómo puedo hacer eso? ¿Es posible fusionar dos formularios en este caso?
Haga un tipo de formulario que contenga ambas formas secundarias.
class MergedFormType
$builder->add(''topic'', new TopicFormType());
$builder->add(''post'', new PostFormType());
En su controlador simplemente pase una matriz a MergedFormType
public function myAction()
$formData[''topic''] = $topic;
$formData[''post''] = $post;
$form = $this->createForm(new MergedFormType(), $formData);
En caso de que busque fusionar formularios para 2 entidades con una relación uno a muchos o uno a uno; Deberá usar la extensión de colección de formularios del componente Symfony 2. por ejemplo: donde la entidad Task tiene muchas etiquetas
class TaskType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add(''description'');
$builder->add(''tags'', ''collection'', array(''type'' => new TagType()));
}
La representación se puede hacer de esta manera
{{ form_start(form) }}
<h3>Tags</h3>
<ul class="tags">
{# iterate over each existing tag and render its only field: name #}
{% for tag in form.tags %}
<li>{{ form_row(tag.name) }}</li>
{% endfor %}
</ul>
Más detalles: http://symfony.com/doc/2.7/cookbook/form/form_collections.html
También puede asignar la misma entidad a múltiples formularios combinados.
$entity = new Form();
$form = $this->get(''form.factory'')->create(FormType::class, [
''form_builder'' => $entity,
''submit_builder'' => $entity,
]);
FormType.php
<?php
namespace GenyBundle/Form/Type;
use Symfony/Component/Form/AbstractType;
use Symfony/Component/Form/FormBuilderInterface;
use Symfony/Component/Form/Extension/Core/Type;
use Symfony/Component/OptionsResolver/OptionsResolver;
use GenyBundle/Entity/Form;
class FormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(''form_builder'', FormBuilderType::class, [
''data_class'' => Form::class,
''label'' => false, // Important!
])
->add(''submit_builder'', SubmitBuilderType::class, [
''data_class'' => Form::class,
''label'' => false,
])
->add(''save'', Type/SubmitType::class, [
''label'' => ''geny.type.form.save.label'',
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
''translation_domain'' => ''geny'',
]);
}
}
FormBuilderType.php
<?php
namespace GenyBundle/Form/Type;
use GenyBundle/Base/BaseType;
use Symfony/Component/Form/Extension/Core/Type;
use Symfony/Component/Form/FormBuilderInterface;
use Symfony/Component/OptionsResolver/OptionsResolver;
class FormBuilderType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(''title'', Type/TextType::class, [
''attr'' => [
''placeholder'' => ''geny.type.form.title.placeholder'',
],
''empty_data'' => $this->get(''translator'')->trans(''geny.type.form.title.default'', [], ''geny''),
''label'' => ''geny.type.form.title.label'',
''required'' => true,
])
->add(''description'', Type/TextareaType::class, [
''attr'' => [
''placeholder'' => ''geny.type.form.description.placeholder'',
],
''empty_data'' => null,
''label'' => ''geny.type.form.description.label'',
''required'' => false,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
''data_class'' => ''GenyBundle/Entity/Form'',
''translation_domain'' => ''geny'',
]);
}
}
SubmitBuilderType.php
<?php
namespace GenyBundle/Form/Type;
use GenyBundle/Base/BaseType;
use Symfony/Component/Form/Extension/Core/Type;
use Symfony/Component/Form/FormBuilderInterface;
use Symfony/Component/OptionsResolver/OptionsResolver;
class SubmitBuilderType extends BaseType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add(''submit'', Type/TextType::class, [
''attr'' => [
''placeholder'' => ''geny.type.submit.submit.placeholder'',
],
''empty_data'' => $this->get(''translator'')->trans(''geny.type.submit.submit.default'', [], ''geny''),
''label'' => ''geny.type.submit.submit.label'',
''required'' => true,
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
''data_class'' => ''GenyBundle/Entity/Form'',
''translation_domain'' => ''geny'',
]);
}
}
Form.php
<?php
namespace GenyBundle/Entity;
use Doctrine/Common/Collections/ArrayCollection;
use Doctrine/ORM/Mapping as ORM;
use JMS/Serializer/Annotation as Serializer;
use Symfony/Component/Validator/Constraints as Assert;
/**
* @ORM/Table(name="geny_form")
* @ORM/Entity(repositoryClass="GenyBundle/Repository/FormRepository")
* @ORM/ChangeTrackingPolicy("DEFERRED_EXPLICIT")
* @Serializer/ExclusionPolicy("NONE")
*/
class Form
{
/**
* @var int
*
* @ORM/Column(name="id", type="integer")
* @ORM/GeneratedValue(strategy="AUTO")
* @ORM/Id
* @Serializer/Exclude
*/
protected $id;
/**
* @var string
*
* @ORM/Column(name="title", type="string", length=128)
* @Assert/Length(min = 1, max = 128)
* @Serializer/Type("string")
*/
protected $title;
/**
* @var string
*
* @ORM/Column(name="description", type="text", nullable=true)
* @Assert/Length(min = 0, max = 4096)
* @Serializer/Type("string")
*/
protected $description;
/**
* @var ArrayCollection
*
* @ORM/OneToMany(targetEntity="Field", mappedBy="form", cascade={"all"}, orphanRemoval=true)
* @ORM/OrderBy({"position" = "ASC"})
* @Assert/Valid()
* @Serializer/Type("ArrayCollection<GenyBundle/Entity/Field>")
*/
protected $fields;
/**
* @var string
*
* @ORM/Column(name="submit", type="text")
* @Assert/Length(min = 1, max = 64)
* @Serializer/Type("string")
*/
protected $submit;
}
Resultado: