Php 使用symfony表单组件重构普通请求数据解析

Php 使用symfony表单组件重构普通请求数据解析,php,forms,symfony,symfony-forms,Php,Forms,Symfony,Symfony Forms,因此,我有一个控制器,在这里使用这个动作方法: public function addAction(Request $request) { $tournamentId = $request->request->get('tournament_id'); $externalId = $request->request->get('external_id'); $eventDate = $request->request->get('eve

因此,我有一个控制器,在这里使用这个动作方法:

public function addAction(Request $request)
{
    $tournamentId = $request->request->get('tournament_id');
    $externalId = $request->request->get('external_id');
    $eventDate = $request->request->get('event_date');

    if (!is_numeric($tournamentId) || !is_numeric($externalId) || empty($eventDate)) {
        throw new InvalidArgumentException('Invalid POST data');
    }

    $em = $this->getDoctrine()->getManager();
    $tournament = $em->getRepository('BakingBankCoreBundle:TournamentGame')->find($tournamentId);

    if (empty($tournament)) {
        throw new InvalidArgumentException('Invalid tournament ID');
    }

    $entity = new TournamentInstance();
    $entity->setTournament($tournament);
    $entity->setExternalId($externalId);
    $entity->setEventDate(new DateTime($eventDate));

    $em->persist($entity);
    $em->flush();

    return new JsonResponse(['id' => $entity->getId()]);
}
我的同事希望我重构它以使用表单。问题是-TournamentInstance字段如下所示:

/**
 * @var TournamentGame
 *
 * @ORM\ManyToOne(targetEntity="TournamentGame")
 * @ORM\JoinColumn(name="tournament_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
 */
private $tournament;

/**
 * @var string
 *
 * @ORM\Column(name="external_id", type="string", length=64, nullable=false)
 */
private $externalId;

/**
 * @var DateTime
 *
 * @ORM\Column(name="event_date", type="date", nullable=false)
 */
private $eventDate;
POST数据不是从twig表单发送的,而是从JS中的AJAX请求发送的,在JS中,数据是从代码中的几个位置收集的


我怎样才能做到这一点,这值得吗?我知道他希望一切都标准化,但我认为他比我更理想(这说明了很多)。

不需要太多工作,因为您只需要将实体属性映射到表单字段:

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextType;

public function addAction(Request $request)
{
    $entity = new TournamentInstance();

    // you can set default value with $entity->setEventDate(new DateTime('tomorrow'))
    // before passing it as data to the form builder

    $form = $this->createFormBuilder($entity) // set the default value
        // you need to add a field for each property accordingly to its name
        ->add('tournament', EntityType::class) // will output a select with all tournaments
        ->add('external_id', TextType::class)
        ->add('external_date', DateTimeType::class)

    $form->handleRequest($request) // will synchronize post values to the new entity

    if ($form->isSubmitted() && $form->isValid()) { // validate the form
        $em = $this->getDoctrine()->getManager();

        $filledEntity = $form->getData();

        $em->persist($filledEntity);
        $em->flush();

        return new JsonResponse(['id' => $filledEntity->getId()]);
    }

    if (0 < count($form->getErrors)) {
        return new JsonResponse(['errors' => $form->getErrors()]);
    }

    return new JsonResponse(['errors' => ['No data matching form type']]);
}
使用Symfony\Bridge\doctor\Form\Type\EntityType;
使用Symfony\Component\Form\Extension\Core\Type\DateTimeType;
使用Symfony\Component\Form\Extension\Core\Type\TextType;
公共函数addAction(请求$Request)
{
$entity=新的TournamentInstance();
//您可以使用$entity->setEventDate(new DateTime('明天')设置默认值
//在将其作为数据传递给表单生成器之前
$form=$this->createFormBuilder($entity)//设置默认值
//您需要为每个属性的名称添加相应的字段
->add('tournament',EntityType::class)//将输出一个包含所有锦标赛的选择
->添加('external_id',TextType::class)
->添加('external_date',DateTimeType::class)
$form->handleRequest($request)//将把post值同步到新实体
如果($form->isSubmitted()&&&$form->isValid()){//验证表单
$em=$this->getDoctrine()->getManager();
$filledEntity=$form->getData();
$em->persist($filledEntity);
$em->flush();
返回新的JsonResponse(['id'=>$filledEntity->getId()]);
}
如果(0getErrors)){
返回新的JsonResponse(['errors'=>$form->getErrors()]);
}
返回新的JsonResponse(['errors'=>['No data matching form type']]);
}
如果需要微调验证,可以在类属性中使用约束作为注释


您使用的是哪个版本的symfony?@Heah-2.7,但计划将此项目移至3.0。我不使用HTML表单来填充数据。没有选择所有锦标赛,只有JavaScript中的ID。不管怎么说,我发现数据转换器应该是一个不错的选择,但我一直严格遵循官方指南,但它总是给我错误。好吧,除了返回,它的工作原理是一样的。我已经相应地更新了我的答案,希望能有所帮助。我的问题是,无论我做了什么尝试,表单都没有与我提供的数据一起提交。要么有类型错误,要么表单没有错误,也没有提交。但不管怎样,我放弃了这个想法,因为当我已经有了没有表单的工作代码时,有太多的头痛和时间试图解决这个问题。无论如何,使用表单都会导致大量代码膨胀,因为我必须为锦标赛属性使用数据转换器。