Symfony2 DataTransformer用于选择字段

时间:2014-02-17 15:12:27

标签: php mongodb symfony choicefield

我正在尝试创建自定义选项列表字段。 几乎所有看起来都有效,除了编辑部分的预选值。

基本上我正在创建一个具有多个对象类型的混合列表字段(后端是mongodb),我知道这是一种肮脏的操作方式,但我找不到更好的解决方案(保持简单)。 这个过程正常,我在后端有一个混合对象,我可以选择编辑表单中的哪一个,但表单没有显示预选(使用从mongo中提取的值)

<?php
namespace www\DefaultBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use www\DefaultBundle\Form\DataTransformer\AccessorioTransformer;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class AccessorioType extends AbstractType
{
    /**
     * @var ObjectManager
     */
    private $om;

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


    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $transformer = new AccessorioTransformer($this->om);
        $builder->addModelTransformer($transformer);
    }


    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $choices = array();
        $data = array();
        $documents = array(
            'Document1',
            'Document2',
            'Document3',
            );

        foreach ($documents as $document)
        {
            $objects = $this->om->getRepository('wwwDefaultBundle:' . $document)->findAll();
            foreach ($objects as $object)
            {
               if (@!$object->getId()) print_r($object);
               $key = sprintf("%s_%s", $object->getId(), basename(str_replace('\\', '/', get_class($object))));
               $value = sprintf("%s (%s)", $object, basename(str_replace('\\', '/', get_class($object))));
               $choices[$key] = $value;
            }
        }

        $resolver->setDefaults(array(
            'choices'  => $choices,
            'expanded' => false,
            'multiple' => true,
        ));

    }


    public function getParent()
    {
        return 'choice';
    }

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

datatransformer:

<?php
namespace www\DefaultBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\ObjectChoiceList;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;

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

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


    public function transform($values)
    {
        return array();
        // i tried everything here but none working

    }


    public function reverseTransform($values)
    {
        if (!$values) return null;

        $array = array();

        foreach ($values as $value)
        {
          list($id, $type) = explode("_", $value);
          $array[] = $this->om->getRepository('wwwDefaultBundle:' . $type)->find($id);
        }

        return $array;
    }
}

表单构建器:

<?php

namespace www\DefaultBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class ValvolaType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder

            // [snip]

            ->add('ref',
                'accessorio',
                array(
                    'label_attr' => array('class' => 'control-label col-sm-2'),
                    'attr'       => array('class' => 'form-control '),
                ))
        ;
    }

    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'www\DefaultBundle\Document\Valvola',
            'attr'       => array('class' => 'press form-horizontal'),
        ));
    }

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

有人遇到同样的问题吗?如何改变“选择”领域?如何在同一个字段中管理混合对象? 有人可以启发我吗?

此致

2 个答案:

答案 0 :(得分:4)

我终于找到了解决方案。罪魁祸首是数据变换器(我当然是:-)) 通过这种方式,表单显示了预选值:

<?php
namespace www\DefaultBundle\Form\DataTransformer;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Extension\Core\ObjectChoiceList;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\TaskBundle\Entity\Issue;

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

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


    public function transform($values)
    {
        if ($values === null) return array();

        $choices = array();
        foreach ($values as $object)
        {
           $choices[] = sprintf("%s_%s", $object->getId(), basename(str_replace('\\', '/', get_class($object))));
        }

        return $choices;
    }


    public function reverseTransform($values)
    {
        if (!$values) return array();

        $array = array();

        foreach ($values as $value)
        {
          list($id, $type) = explode("_", $value);
          $array[] = $this->om->getRepository('wwwDefaultBundle:' . $type)->find($id);
        }

        return $array;
    }
}

答案 1 :(得分:0)

在大多数使用ChoiceType的情况下,transform函数返回的数组应仅包含ID。例如:

public function transform($objectsArray)
{
    $choices = array();

    foreach ($objectsArray as $object)
    {
       $choices[] = $object->getId();
    }

    return $choices;
}

虽然它可能不是原帖的答案,但我很确定googlers会到这里寻找这个提示。