根据表单数据更新db条目

时间:2015-08-17 09:35:43

标签: php forms symfony doctrine-orm

我有一个简单的注册表单,有3个字段。电子邮件,姓名和密码。到现在为止还挺好。我能够创建新用户。当我想编辑用户信息时,问题出现了。

我想仅在html密码字段不为空时才更新数据库中的密码字段

public function editAction(User $user, Request $request)
    {
        $form = $this->createForm(new UserForm(), $user);

        $form->handleRequest($request);

        if($form->isSubmitted() && $form->isValid()){
            $em = $this->getDoctrine()->getManager();
            $em->persist($user);
            $em->flush();
            $this->redirectToRoute('bd_user_list');
        }

        return $this->render('BDUserBundle:User:add.html.twig', [
            'form' => $form->createView()
        ]);
    }

如果我将密码字段留空,我会收到此错误(这是正常的)

An exception occurred while executing 'UPDATE users SET password = ? WHERE id = ?' with params [null, 5]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'password' cannot be null

我已阅读过有关验证小组的信息,但我不确定他们是否可以提供帮助。

//解决方案

UserForm.php

[...]
builder->addEventSubscriber(new UserFormListener());
[...]

UserFormListener.php

<?php

namespace SDUserBundle\Form\EventListener;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class UserFormListener implements EventSubscriberInterface
{
    private $password;

    public static function getSubscribedEvents()
    {
        return array(
            FormEvents::PRE_SET_DATA => 'preSetData',
            FormEvents::POST_SUBMIT => 'postSubmit'
        );
    }

    public function preSetData(FormEvent $event)
    {
        $this->password = $event->getData()->getPassword();
    }

    public function postSubmit(FormEvent $event)
    {
        $data = $event->getData();

        if ($data->getPassword() == false) {
            $data->setPassword($this->password);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

快速解决方案

修改您的代码,如下所示

public function editAction(User $user, Request $request)
{
    $old_pwd = $user->getPassword(); //or whatever the method is called

    $form = $this->createForm(new UserForm(), $user);
    $form->handleRequest($request);

    if($form->isSubmitted() && $form->isValid()){
        $em = $this->getDoctrine()->getManager();
        if (null == $user->getPassword()) {
            $user->setPassword($old_pwd);
        }
        $em->persist($user);
        $em->flush();
        $this->redirectToRoute('bd_user_list');
    }

    return $this->render('BDUserBundle:User:add.html.twig', [
        'form' => $form->createView()
    ]);
}

更优雅的解决方案

这是第一个解决方案,但涉及控制器内部的一些逻辑;也许您需要在其他地方使用该代码,因此您可以将其迁移到FormEvents::PRE_SET_DATA

等表单事件中

因此,您需要修改UserForm,如下所示

use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
[...]

class UserForm extends AbstractType
{
    private $old_pwd;

    [...]
    $builder
        [...] 
        ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
            $data = $event->getData();
            $this->old_pwd = $data->getPassword();
        })
        ->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
            $data = $event->getData();
            if (false == $data->getPassword()) {
                $data->setPassword($this->old_pwd);
                $this->setData($data);
            }
        })
}

我真的不知道第二种方法是否有效,因为我现在无法对其进行测试,但FormEvents可以帮助您完成所需的工作。

另一种方法,不是很好吗?

也许您可以直接修改用户设置器

class User
{
    [...]
    public function setPassword($pwd)
    {
        if ($pwd) {
            $this->pwd = //logic here to store a safe pwd
        }
    }
}

为什么第三种解决方案是最糟糕的,我让你找到自己;)

旁注

只是为了让您知道isValid()关注来自Symfony2.3的已提交控件,因此您不需要isSubmitted()明确控制