Symfony2 DataTransformers - Как се трансформира обратно без ID или уникални стойности?

Имам колекция от обекти PhoneNumber за всеки обект за контакт (име, имейл). PhoneNumber е разбит на код на област, обмен, суфикс, разширение и след това селектор на тип (работа, дом, мобилен). Искам да използвам DataTransformer, така че числото да може да се показва в едно поле на формуляр вместо в 4 различни текстови полета. Телефонните номера не са уникални в базата данни.

АКТУАЛИЗИРАНО: Как да получа достъп до пълния обект, когато трансформирам от низовата версия обратно към обекта? По-рано се сблъсках с този проблем и в крайна сметка поставих идентификатора на обекта в скоби в текстовото поле и след това ги направих с регекс в трансформацията, за да мога да направя заявка за получаване на обекта.

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);
}

Преобразувател на PhoneNumberToString:

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?
}

person mhoff    schedule 25.10.2012    source източник


Отговори (2)


Ще трябва да подадете мениджър на обекти чрез инжектиране на конструктор, след което да работите с това, както обикновено.

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;
    }
}
person Bill H    schedule 14.03.2013

Съжалявам за липсата на актуализации, но намерих прилично решение на този проблем. Добавих метод setPhone към обекта PhoneNumber, който изглежда се извиква автоматично след обратната трансформация. В моя трансформатор добавих регулярен израз, за ​​да разделя телефонния си номер на съответните му секции и след това добавих всяка секция към масив. Този масив се връща от трансформатора, който след това се използва от setPhone за актуализиране на обекта PhoneNumber.

Моят метод setPhone в обекта PhoneNumber:

/**
 * 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:

/**
 * 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;
}
person mhoff    schedule 09.01.2013