Forms - advanced

有时你可能对你的 Forms 有更复杂的需求。 你可能已经知道 Mautic 构建于 Symfony 框架之上,因此有很多与表单相关的特性可供使用。 你可以阅读更多关于此的信息:Symfony 5 form classes。 本节重点介绍一些复杂但常见的用例:

  • 与 Symfony 提供的各种标准表单类型(如文本字段、选择字段等)不同的自定义表单类型。

  • 数据清洗

  • 动态表单修改

  • 数据验证

自定义表单类型

正如在前面部分引用的 Symfony 文档中所述,表单类型类是最佳方法。 Mautic 通过 bundle 的配置文件轻松注册 Form type services。 请参阅:ref:plugins/config:Service config items 部分。

数据清洗

表单数据不会自动进行清洗。 Mautic 提供了一个表单事件订阅器来处理此操作。

在你的 Form type class 中,注册 Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber 事件订阅器。

提供给 CleanFormSubscriber 的数组应包含表单字段的名称作为键,以及用于清洗数据的掩码作为值。 任何未指定的表单字段默认使用 clean 掩码。

<?php
// plugins/HelloWorldBundle/Form/Type/WorldType.php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle\Form\Type;

use Mautic\CoreBundle\Form\EventListener\CleanFormSubscriber;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class WorldType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder->addEventSubscriber(
            new CleanFormSubscriber(
                [
                    'content'    => 'html',
                    'customHtml' => 'html'
                ]
            )
        );
    }
}

动态表单修改

如果需要根据已提交的数据来操作表单,请使用表单事件监听器。 这在更改定义的字段、调整约束或根据已提交的值更改选择项等情况下非常有用。 请参阅 Symfony 关于此的文档:Symfony 5 dynamic form modification

数据验证

请查看 Symfony 的表单验证文档以获取一般概述:Symfony 5 form validation

有两种常见的验证表单数据的手段。

使用实体静态回调

如果表单的基础数据是 Entity 对象,则可以在 Entity 类中定义一个静态方法 loadValidatorMetadata。 当 Symfony 处理表单数据时,此方法会自动调用。

A Form 也可以使用 :xref:`validation_groups<Symfony 5 Form validation groups> 来改变数据验证的顺序,或者仅在满足特定条件时进行验证。 例如,只有当第一个密码字段通过验证时,才验证确认密码字段。 在表单类型类中注册验证组时,可以使用静态回调函数来确定 Symfony 应使用的验证组。

<?php
// plugins/HelloWorldBundle/Form/Type/WorldType.php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Mapping\ClassMetadata;

class WorldType extends AbstractType
{
    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class'        => 'MauticPlugin\HelloWorld\Entity\World',
            'validation_groups' => array(
                'MauticPlugin\HelloWorld\Entity\World',
                'determineValidationGroups',
            )
        ));
    }

    public static function loadValidatorMetadata(ClassMetadata $metadata)
    {
        $metadata->addPropertyConstraint(
            'name',
            new NotBlank(
                array(
                    'message' => 'mautic.core.name.required'
                )
            )
        );

        $metadata->addPropertyConstraint(
            'population',
            new NotBlank(
                array(
                    'message' => 'mautic.core.value.required',
                    'groups'  => array('VisitedWorld')
                )

            )
        );
    }

    public static function determineValidationGroups(Form $form)
    {
        $data   = $form->getData();
        $groups = array('AllWorlds');

        if (!$data->getId() || ($data->getId() && $data->getVisitCount() > 0)) {
            $groups[] = 'VisitedWorld';
        }

        return $groups;
    }
}

Using constraints

A Form type service 也可以在定义表单字段时注册 Constraints

<?php
// plugins/HelloWorldBundle/Form/Type/WorldType.php

declare(strict_types=1);

namespace MauticPlugin\HelloWorldBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Form;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Validator\Constraints\NotBlank;

```markdown class WorldType extends AbstractType

{

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

$builder->add(

‘name’, ‘text’, array(

‘label’ => ‘mautic.core.name’, ‘label_attr’ => array(‘class’ => ‘control-label’), ‘attr’ => array(

‘class’ => ‘form-control’

), ‘constraints’ => array(

new NotBlank(
array(

‘message’ => ‘mautic.core.value.required’

)

)

)

)

);

}

}

```