Symfony2 - 将DataTransformer应用于表单中的集合

时间:2013-05-22 16:41:16

标签: symfony collections doctrine

我需要创建一个Symfony2表单并向Collection添加数据转换器。我有一个StudentType表单,其中包含一个隐藏字段,其中包含一个唯一的学生邮件。案例使用是一个包含多个学生(oneToMany关系)的课程,我有一个课程表单,其中包含通过邮件或姓名搜索用户的建议输入。然后,通过javascript我动态添加表单集合并设置隐藏值邮件与在建议输入上选择的学生邮件。直到这里一切都正常运行,但我需要应用一个数据转换器,将这些隐藏字段与学生邮件转换为与这些邮件对应的Student对象数组。因为在控制器中,它会抛出异常,因为Course Entity的addStudent()方法需要一个Student对象。

class StudentType extends AbstractType
{
    private $container;

    public function __construct(Container $container)
    {
       $this->container = $container;
    }

    public function buildForm(FormBuilderInterface $builder, array $options)
    {

        $builder->add(
            $builder->create('mail','hidden', array(
                'required' => false,
                'label' => '',
                'attr' => array(
                    'class' => 'student_mail')
                )
        ));

    }

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

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

}

我已经将该类定义为注入服务容器的服务:

backoffice.form.courseforms.student:
    class: ...\StudentType
    arguments:
        - '@service_container'
    tags:
        - { name: form.type, alias: CourseStudents }

因此,在CourseType表单中,我添加了一组StudentType表单并应用了DataTransformer:

$transformer = new StudentMailTransformer($this->container->get('doctrine')->getManager());
....
$builder->add($builder->create('students', 'suggest', array(
            'type' => 'CourseStudents',
            'attr' => array(
                'title' => 'Search students',
                'placeholder' => 'Search students by mail',
                'class' => 'student_suggest')
            ))->addModelTransformer($transformer)
        )

最后,数据转换器:

class StudentMailTransformer implements DataTransformerInterface
{
/**
 * @var ObjectManager
 */
private $om;

/**
 * @param ObjectManager $om
 */
public function __construct(ObjectManager $om)
{
    $this->om = $om;
}

public function transform($student)
{
    $array = new \Doctrine\Common\Collections\ArrayCollection();


    if (null === $student->toArray()) {
        return $array;
    }

    return $array;
}

public function reverseTransform($students)
{
    $students = new \Doctrine\Common\Collections\ArrayCollection();

    $array = $students->toArray();

    foreach ($array as $value) {

        $student = $this->om->getRepository('AcmeUserBundle:Student')->findOneBy(array('mail' => $value['mail']));

        if (null === $student) {
            throw new TransformationFailedException(sprintf(
                'Student with mail "%s" does not exist!',
                $mail
            ));
        }

        $students->add($student);
    }

    return $students;
}
}

因此,我想获得一个数据转换器,它将一个StudentType集合转换为一个名为mail的字段,并将其转换为与这些邮件对应的Student对象集合。

提前致谢。

1 个答案:

答案 0 :(得分:1)

您要找的不是DataTransfomer,而是entity field type

您可以通过嵌入具有实体字段类型的子表单来进行此类输入....由query_builder过滤以仅匹配课程中的学生。

您可以使用multi选项将其渲染为html中的select或复选框,并使用JavaScript轻松将其转换为自动提示输入。

$builder->add('users', 'entity', array(
    'class'         => 'AcmeHelloBundle:Student',
    'multiple'      => true
    'property'      => 'email',
    'query_builder' => function(EntityRepository $er) {

        return $er->createQueryBuilder('u')
            ->orderBy('u.username', 'ASC');
            ->where('u.course = :course')
            ->setParameter('course', $course)
    },
));

现在使用jQuery Chosen之类的内容作为自动填充建议。

使用另一个queryBuilder将标签填充为“Firstname Lastname(mail@host.com)”。