Symfony2 DataTransformers - 如何在没有ID或唯一值的情况下进行转换?

时间:2012-10-25 14:23:53

标签: php forms symfony symfony-2.1

我为每个联系人(姓名,电子邮件)实体提供了一组PhoneNumber实体。 PhoneNumber分为区域代码,交换,后缀,扩展名,然后是类型选择器(工作,家庭,移动)。我想使用DataTransformer,以便数字可以显示在单个表单字段而不是4个不同的文本框中。这些语音在数据库中并不是唯一的。

更新:如何在从字符串版本转换回实体时访问完整实体?我之前遇到过这个问题并最终将实体的ID放在文本字段中的括号内,然后在变换中将它们重新出现,以便我可以进行查询以获取实体。

phonenumber_combined是一个引用我的PhoneNumberCombinedType类的自定义表单类型服务。

我在联系人中收集电话的添加方法:

->add('phones', 'collection', array(
            'label'     => 'Phones',
            'type'      => new PhoneNumberType(),
            'allow_add' => true,
            'allow_delete' => true
            ))
        ; 

PhoneNumberType buildForm函数:

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('phone', 'phonenumber_combined')
        ->add('type', 'entity',
            array('class'   => 'Test\Bundle\SystemBundle\Entity\Type',
            'property'      => 'name',
            'query_builder' => function(EntityRepository $er){
                return $er->createQueryBuilder('type')
                ->where('type.type = :t')
                ->orderBy('type.name', 'ASC')
                ->setParameter('t', 'PhoneNumber');
            }))
        ;           
}

PhoneNumberCombinedType服务:

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

    $builder->addViewTransformer($transformer);
}

PhoneNumberToStringTransformer:

public function transform($phonenumber)
{
    if (null === $phonenumber) {
        return null;
    }

    return $phonenumber->__toString();       
}

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

    // PHONE NUMBER IS JUST A STRING AT THIS POINT, HOW DO I GET THE ENTITY?
}

2 个答案:

答案 0 :(得分:3)

你必须通过构造函数注入传递一个对象管理器,然后像往常那样对它进行操作。

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

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

    public function transform($phonenumber)
    {
        if ($phonenumber === null) {
            return null;
        }

        return $phonenumber->__toString();
    }

    public function reverseTransform($phonenumber)
    {
        if (!$this->phonenumber) {
            return null;
        }

        $phoneEntity = $this->om
            ->getRepository('{REFERENCE_TO_THE_ENTITY}')
            ->findOneBy(array('phonenumber' => $phonenumber));

        if ($phoneEntity === null) {
            throw new TransformationFailedException();
        }

        return $phoneEntity;
    }
}

答案 1 :(得分:0)

很抱歉没有更新,但我找到了解决此问题的合适解决方案。我向PhoneNumber实体添加了一个 setPhone方法,该实体似乎在反向转换后自动调用。在我的变压器中,我添加了一个正则表达式,将我的电话号码分成各自的部分,然后将每个部分添加到一个数组中。该数组由变换器返回,然后由setPhone用于更新PhoneNumber对象。

我的PhoneNumber实体中的setPhone方法:

/**
 * Used by PhoneNumberToStringTransformer to set Entity data
 * @param array $phone_data
 */
public function setPhone($phone_data)
{
    if($phone_data == null) {
        $this->setAreaCode(null);
        $this->setExchange(null);
        $this->setSuffix(null);
        $this->setExtension(null);
        return $this;
    }

    $this->setAreaCode($phone_data['AreaCode']);
    $this->setExchange($phone_data['Exchange']);
    $this->setSuffix($phone_data['Suffix']);
    $this->setExtension($phone_data['Extension']);

    return $this;
}

我的PhoneNumberToStringTransformer中的reverseTransform:

/**
 * Transforms a phonenumber string to an array that will be passed to setPhone
 * which will handle setting each entity field.
 *
 * @param  string $string Phone number string
 * @return (array) areaCode, exchange, suffix and extension
 */
public function reverseTransform($string)
{
    if (!$string || strlen($string) == 0) {
        return null;
    }

    // Split phone number into array for areaCode, exchange, suffix, and extension
    $pattern = '/(\d{3})?-?(\d{3})?-?(\d{4})?( x(\d+))?/';
    preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER);

    $phone_data = array('AreaCode'=>null, 'Exchange'=>null, 'Suffix'=>null, 'Extension'=>null);

    $counter = 1;
    foreach($phone_data as $key => $value) {
        if($counter == 4)
            $counter = 5;

        if(isset($matches[$counter][0]) && $matches[$counter][0] !== '') {
            $phone_data[$key] = $matches[$counter][0];
        } else {
            $phone_data[$key] = null;
        }
        $counter++;
    }

    return $phone_data;
}