douyan1453 2016-08-31 09:26
浏览 28

Symfony Form CollectionType,包含新/现有实体的API帖子

Building an internal API endpoint which allows another service to update specific fields for users, identified by email addresses. If the user does not exist, it needs to be created.

The code is working perfectly fine providing only new users are submitted.

This is the POST request to the API endpoint.

[
    {
        "email":"existing@user.com",
        "favouriteFood": "pizza"
    },
    {
        "email":"new@user.com",
        "favouriteFood": "sweets"
    }
]

Controller action

public function postUsersAction(Request $request)
{
    $form = $this->createForm(UserCollectionType::class);
    $form->submit(['users' => json_decode($request->getContent(), true)], true);

    if (!$form->isValid()) {
        return $form;
    }

    /** @var User $user */
    foreach ($form->getData()['users'] as $user) {
        $this->userManager->updateUser($user);
    }

    $this->em->flush();

    return $form->getData()['users'];
}

UserCollectionType

class UserCollectionType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->add('users', 'collection', [
            'allow_add' => true,
            'by_reference' => false,
            'type' => UserType::class
        ]);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'csrf_protection' => false,
            'cascade_validation' => true
        ]);
    }

    public function getBlockPrefix()
    {
        return '';
    }
}

UserType

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('email')
            ->add('favouriteFood', TextType::class);
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => User::class,
            'validation_groups' => ['user_api'],
            'cascade_validation' => true
        ]);
    }
} 

How can I update the above code so that it will check to see if the user exists first, otherwise continue to create a new one how it's currently working.

I'd have assumed a DataTransformer could have been used, but not exactly how.

EDIT: Proposed solution by ShylockTheCamel

Inside the controller.

$post = json_decode($request->getContent(), true);
$users = [];

foreach ($post as $userRaw) {
    $user = $this->em->findOneBy($userRaw['email']); // example search logic in the DB

    if (!$user) {
        $user = new User();
    }

    $users[] = $user;
}

$form = $this->createForm(UserCollectionType::class, $users);
$form->submit(['users' => $post], true);
  • 写回答

1条回答 默认 最新

  • dsfsdf5646 2016-08-31 09:41
    关注

    If I understand correctly, your user(s) entity(ies) exist when you enter the foreach loop. So you must create them in the form creation process. In that case, why not check th existence of a user in one of your form validators?

    评论

报告相同问题?

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么