表单验证 - 覆盖实体字段的加载

时间:2014-01-09 17:47:58

标签: validation symfony-2.3

我正在构建基于FOSRestBundle的REST API。为了创建一些实体,使用者在POST HTTP请求中发送以下JSON:

{
   "myentity":
       { 
             "field1": "field1 value", 
             "field2": "field2 value", 
             "user": 1,
             "createdAt": {"date":{"year":"2012", "month":"11", "day":"8"}, "time":{"hour":"13","minute":"22"}}
        }
}

字段用户包含用户的ID。我想通过用户电子邮件或电话号码进行更改。我试图找出如何创建实体用户的实例并将其传递给myentity实例。

以下是我的表单的示例代码:

<?php

namespace Acme\DemoBundle\Form;

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

class MyFormType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('field1')
            ->add('field2')
            ->add('createdAt')
            ->add('user');
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Acme\DemoBundle\Entity\MyEntity',
            'csrf_protection' => false
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'myform';
    }
}

这就是我验证API使用者提供的数据的方式:

/**
 * @Rest\View
 */
public function saveAction()
{
    return $this->processForm(new MyEntity());
}

/**
 * @Rest\View
 */
private function processForm(MyEntity $myEntity)
{
    $form = $this->createForm(new MyFormType(), $myEntity);
    $form->bind($this->getRequest());

    if ($form->isValid()) {
        //$position->save();
        $response = new Response();
        $response->setStatusCode(204);

        return $response;
    }
    return $this->view($form, 400);
}

1 个答案:

答案 0 :(得分:1)

解决!

我使用了DataTransformer:http://symfony.com/en/doc/current/cookbook/form/data_transformers.html

您必须创建一个DataTransformer:

<?php

namespace Acme\DemoBundle\Form;

use Symfony\Component\Form\DataTransformerInterface;
use Symfony\Component\Form\Exception\TransformationFailedException;
use Doctrine\Common\Persistence\ObjectManager;
use Acme\DemoBundle\Entity\User;

class PhoneNumberToUserTransformer implements DataTransformerInterface {

    /**
     * @var ObjectManager
     */
    private $om;

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

    /**
     * Transforms an object (User) to a string (phonenumber).
     *
     * @param  User|null $issue
     * @return string
     */
    public function transform($user) {
        if (null === $user) {
            return "";
        }

        return $user->getPhonenumber();
    }

    /**
     * Transforms a string (phonenumber) to an object (User).
     *
     * @param  string $phonenumber
     * @return User|null
     * @throws TransformationFailedException if object (user) is not found.
     */
    public function reverseTransform($phonenumber) {
        if (!$phonenumber) {
            return null;
        }

        $user = $this->om
                ->getRepository('AcmeDemoBundle:User')
                ->findOneBy(array('phonenumber' => $phonenumber))
        ;

        if (null === $user) {
            throw new TransformationFailedException(sprintf(
                    'L\'utilisateur avec le numéro "%s" ne peut pas être trouvé!', $phonenumber
            ));
        }

        return $user;
    }

}

?>

在表单定义中:

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

    $entityManager = $options['em'];
    $transformer = new PhoneNumberToUserTransformer($entityManager);

    $builder
            ->add('field1')
            ->add('field2')
            ->add('createdAt')
            ->add($builder->create('user', 'text')->addModelTransformer($transformer));
}

/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver) {
    $resolver->setDefaults(array(
        'data_class' => 'Acme\DemoBundle\Entity\MyEntity',
        'csrf_protection' => false,
        'em' => null
    ));
}

最后在控制器中:

$form = $this->createForm(new MyFormType(), $myentity, array(
    'em' => $this->getDoctrine()->getManager()
));