3

我有自己的验证表单部分的概念。它依赖于这样一个事实,即实体的每个属性都有自己的验证组 pe

class User extends BaseUser
{

    /**
     * @ORM\Column(type="smallint")
     * @Assert\NotBlank(groups={"registration, "validation_height"}, message="Bitte überprüfen Sie Ihre Angabe und geben Sie Ihre korrekte Körpergröße ein.
")
     */
    protected $height;

    /**
     * @ORM\Column(type="string", length=10, nullable=false, columnDefinition="ENUM('male', 'female')")
     * @Assert\NotBlank(groups={"registration", "validation_gender"}, message="Bitte geben Sie Ihr Geschlecht an.")
     */
    protected $gender;

    /**
     * @Assert\True(groups={"registration", "validation_agreeTerms"}, message="Bitte bestätigen Sie die AGB und Datenschutzbestimmungen.")
     */
    protected $agreeTerms;

带表格类型

class RegistrationType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder
            ->add('email', NULL, array('label' => 'E-Mail'))
            ->add('username', NULL, array('label' => 'Benutzername'))
            [...]
            ->add('agreeTerms', 'checkbox', array('label' => false))
        ;

在我的 Ajax 控制器中,我正在动态设置验证组,因此有一个 Javascript 函数可以强制发送每个可见的表单字段(包括未选中的复选框)——默认情况下,Web 浏览器不会发送未选中的复选框。

class AjaxController extends BaseController
{
    protected function validateRegistrationFields($request) {
        $return = array();
        $groups = array();
        $data = $request->get('registration', array());
        foreach (array_keys($data) as $field) $groups[] = 'validation_' . preg_replace('/[^a-zA-Z0-9_]/', '', $field);

        $userManager = $this->container->get('fos_user.user_manager');
        $user = $userManager->createUser();

        $form_type = new RegistrationType();
        $form = $this->createNamedForm('registration', $form_type, $user, array(
            'validation_groups' => $groups,
            'csrf_protection' => false,
        ));
        $form->bind($request);
        if (!$form->isValid()) $return = $this->getFormErrors($form, true, 'registration');
        return $return;
    }

因此,通过使用我的 Javascript 函数,我可以确定,它registration[agreeTerms]包含在POST请求中并设置了相关的验证组validation_agreeTerms。问题是,在使用 JS 函数提交表单时,它的值$agreeTerms始终是。true我相信这依赖于 Symfony 的行为,它假设checkbox请求中包含的 type 的表单字段,无论值如何,都是正确的。当通过真实浏览器(而不是 Ajax)提交表单时POST,复选框不包含在POST数据中,一切都很好。

一个例子POST看起来像

registration[email]: example@example.com
registration[username]: sunny123
registration[agreeTerms]:

如您所见,agreeTerms是用空数据提交的,因为它没有被检查,但是Symfony似乎在将true请求绑定到表单时对其进行了转换,仅基于该字段/属性包含在POST数据中的事实。有没有办法让提交的带有空值的复选框POST被解释为false

4

1 回答 1

2

PreBind 监听器表单在这里很有用。关于表单监听器。似乎可以在绑定 ( $form->bind()) 之前更改数据。考虑这个例子:

class SetDataAgreeTermedSubscriber implements EventSubscriberInterface
{

    private $factory;

    public function __construct(FormFactoryInterface $factory)
    {
        $this->factory = $factory;
    }

    public static function getSubscribedEvents()
    {
        return array(FormEvents::PRE_BIND => 'preBind');
    }

    public function preBind(FormEvent $event)
    {
        $fdata = $event->getData();

        if ((boolean)$fdata['agreeTerms'] !== true) {
            unset($fdata['agreeTerms']);
        }

        $event->setData($fdata);
}
于 2013-10-01T16:20:58.797 回答