marcel-maqsood/mezzio-middleware-formhandler

中间件表单处理器是一个PSR-15中间件,它为Laminas/Mezzio应用程序中的表单数据提供处理功能

v1.0.30 2024-05-23 13:26 UTC

This package is auto-updated.

Last update: 2024-09-23 14:08:03 UTC


README

Software License

这个库允许您处理您的表单,检查缺失的字段,并且仅使用您真正期望提交的字段。

安装

运行以下命令以安装此库

$ composer require marcel-maqsood/mezzio-middleware-formhandler:dev-master

信息

如果您的表单中有在配置中未定义的字段,由于安全原因,处理器将不会使用它们。"adapter"不再是对DataAdapters的正确关键字,现在关键字是"adapters",因为Formhandler现在能够一次使用多个适配器。

请注意:如果"adapters"包含一个条目"null",那么在该条目之后的适配器将不会使用,因为null会将数据传递到管道中。

文档

在文档的底部,我将向您展示如何快速构建配置的示例。

实现

要实现中间件,请将您的路由文件中的路由添加一个路由,将请求传递给中间件

 $app->route(
     '/formhandler[/]',
     [
         MazeDEV\FormularHandlerMiddleware\FormularHandlerMiddleware::class,
     ],
     ['POST'],
     'formHandler'
 );

由于我们的FormHandler现在是真正的中间件,您甚至可以像这样实现它

 $app->route(
     '/formhandler[/]',
     [
         MazeDEV\FormularHandlerMiddleware\FormularHandlerMiddleware::class,
         App\Handler\YourHandler::class
     ],
     ['POST'],
     'formHandler'
 );

之后,请确保在您的config/autoload文件夹中提供一个配置文件,该文件包含中间件需要检查表单的所有内容。我们建议您使用我们的配置文件/config/form-config.local.php,将其粘贴到您的/config/autoload/文件夹中,并根据您的需要调整它。

所需数据

表单处理器需要JSON-、Multidata-或纯POST请求才能正常运行,并以JSON响应,描述正在发生的事情。

  • 您可以通过常规方式提交表单(按钮type="submit" form method="post")或通过AJAX来调用表单处理器。如果您通过AJAX进行操作,可以使用我们的基础JavaScript来根据处理器的需求准备表单。

重要提示

  • 本项目包含一个基本的JavaScript/js/FormToJSON.js,当使用AJAX请求时,它对于将数据发送到表单处理器非常重要。您可以实现自己的逻辑,但您可能需要从开始。

  • 在您的表单中定义一个<input type="hidden" name="data[config]" value="YourFormName">字段至关重要。该字段为我们表单处理器提供有关必须验证的表单的必要信息。

  • 此外,每个输入必须以"data"开头,如下所示:<input type="hidden" name="data[config]" value="aValue"/>。如果未遵循此格式,则输入将不会被我们的表单处理器识别。

HTML示例

```html
<form id="aId" method="post">
    <input type="hidden" name="data[config]" value="aValue"/>
    <div class="row mb-1">
        <div class="col-6">
            <input id="surname" name="data[nachname]" type="text" class="form-control bg-dark"
            placeholder="Surname" required/>
        </div>
        <div class="col-6">
            <input id="Name" name="data[name]" type="text" class="form-control bg-dark"
            placeholder="Name" required/>
        </div>
    </div>
    <div class="row mt-3">
        <div class="col-12">
            <div class="form-group">
                <label class="text-muted label-center">Empty Fields will be ignored.</label>
                <button id="submit" type="submit" class="btn btn-success w-100">Submit</button>
            </div>
        </div>
    </div>
</form>
```

适配器

目前有3个工作适配器

  • phpmail
    定义如下
    'adapters' => [
      'phpmail' => [
          'reply-to' => [
              'status' => true,
              'field'  => 'mail',
          ],
              'recipients' => ['example@example.com'],
              'subject'    => 'subject',
              'sender'     => 'sender@example.com',
              'senderName' => 'Form', 
              'template'   => 'app::test',
      ],
    ],
    phpmail通过PHP方法:mail()发送邮件(正如您可能期望的那样)。
  • smtpmail
    定义如下
    'adapters' => [
      'smtpmail' => [
          //same as on phpmail but includes:
          'email_transfer' => [
              'method' => 'smtpmail',
              'config' => [
                  'service'    => 'smtp.googlemail.com',
                  'port'       => '465',
                  'encryption' => 'ssl',
                  'email'      => 'example@gmail.com',
                  'password'   => 'examplepw',
              ],
          ],
      ],
    ],
    smtpmail通过Swift_SmtpTransport发送邮件。您可以(如后所述)实现它们作为全局或本地适配器,全局适配器将覆盖本地适配器。
  • null
    定义如下
    'adapters' => null,
    如果您定义'adapters' => null,我们的表单处理器将验证后的表单传递到路由中的下一个处理器,该处理器可以对其进行自己的操作。

本地适配器

适配器字段必须直接在表单定义中

    'forms' => [
      'contact' => [
            'fields' => [
                ...
            ],
            'adapters' => [
                null
            ],
        ],
    ],

全局适配器

全局适配器定义在配置的最顶部

'mazeform' => [
    'adapters' => [
        'globalTestAdapter-1' => [
            [   
                'method'         => 'smtpmail',
                'recipients'     => ['example@example.com'],
                'subject'        => 'base subject all forms that uses this specific adaper has',
                'sender'         => 'example@example.com',
                'senderName'     => 'form',
                'template'       => 'app::test',
                'email_transfer' => [
                    'config' => [
                         'service'    => 'smtp.googlemail.com',
                         'port'       => '465',
                         'encryption' => 'ssl',
                         'email'      => 'example@gmail.com',
                         'password'   => 'examplepw',
                    ],
                ],
            ],
        ],
    ],
],

如果您定义了一个全局适配器并希望使用它,请直接在您的表单配置的适配器字段中填写其名称(在本例中:globalTestAdapter-1)。

'forms' => [
    'contact' => [
        'fields' => [
            ...
        ],
        'adapters' => [
            'globalTestAdapter-1',
            'secondAdapter',
            null
        ],
    ],
],

收件人

由于您的表单应该能够发送自动回复,您可以在 php 'recipients' 中定义任意数量的收件人,并且还可以使用 '%submit%',这样处理程序会将此变量映射到您表单中提交的第一个“电子邮件”字段,例如:max.mustermann@mustermail.de,这样max就会知道您的系统已经注意到。

电子邮件模板

您在配置中指定的模板可以通过twig动态生成,然而,从v1.0.23版本开始,模板字段必须包含有效的模板名称。

'template' => 'app::test'

您使用的变量必须是您表单的有效字段,并且也在您的配置中定义。

电子邮件主题

与电子邮件模板类似,电子邮件主题也支持twig渲染器,但是主题不支持模板名称,它是一个纯字符串: 'subject' => 'base subject all forms that uses this specific adaper has {{ some_twig_variable }}'

回复到头

电子邮件适配器可以处理“回复到”电子邮件头,您可以在适配器配置中定义它,如下所示:

'reply-to' => [
    'status' => true,
    'field' => 'mail'
],

回复到仅当

  • 回复到已定义且以下内容正确时才有效:
  • 状态已定义且为true;
  • 字段已定义(并且在配置中存在)或未定义(但在此情况下,您的配置中的一个字段必须是电子邮件类型)
'forms' => [
    'contact' => [
        'fields' => [
            'someFieldName' => [
                'type' => 'email',
            ],
        ],
        'adapters' => [
            ...
        ],
    ],
],

CSRF保护

由于您的表单将在某个时候存储在数据库中或通过电子邮件发送,我们的FormHandler可以检查CSRF令牌以保护您的应用程序免受膨胀。

要使用CSRF保护,您必须安装Mezzio-CSRF并正确配置它。您不需要将字段定义为必需的,但我们建议使用'required' => 'true',只有这样,您的请求才能保证得到CSRF保护。

之后,请确保将其中一个字段定义为'type' => 'csrf'

'contactForm' => [
    'fields' => [
        'somename' => [
            'required' => true
            'type' => 'csrf',
        ],
    ]
]

如果请求提交了无效的CSRF令牌,我们的FormHandler将不会进一步处理请求,而是将带有附加属性'csrfError'的请求传递到管道中,您可以在您的代码中使用此属性。

if($request->getAttribute('csrfError') != null)
{
    //your error handling goes here...
}

多层提交数组

由于您的应用程序可能会发送和接收嵌套数组,例如在联系表单中,我们的处理程序能够从嵌套数组中检索电子邮件字段:您只需将字段定义为 'type' => 'array'即可使用此行为。

'contactForm' => [
    'fields' => [
        'contact' => [
            'type' => 'array',
            'childs' => [
                'salutation' => [
                    'required' => true,
                    'type' => 'text'
                ],
                'name' => [
                    'required' => true,
                    'type' => 'text'
                ],
                'surname' => [
                    'required' => true,
                    'type' => 'text'
                ],
                'email' => [
                    'required' => true,
                    'type' => 'email'
                ],
                'tel' => [
                    'required' => true,
                    'type' => 'int'
                ],
            ]
            //in this case, there is no
        ],
    ],
    'adapters' => [
            ...
    ],
],

必需属性

Formhandler可以检查您的表单中的字段是否为必需的,如果缺失则不接受请求。如果您未定义必需或必需为false,处理程序可能无法获取该字段的值,因为它在请求中缺失。如果您想将字段设置为必需,请将此添加到字段的配置中。

'required' => true

示例

'mazeform' => [
    'adapters' => [
        'globalExampleAdapter-1' => [
            [
                'method'         => 'smtpmail',
                'recipients'     => ['recipient@example.com'],
                'subject'        => 'base subject all forms that uses this specific adaper has',
                'sender'         => 'example@example.com',
                'senderName'     => 'Kontaktformular',
                'template'       => 'app::test',
                'email_transfer' => [
                    'config' => [
                        'service'    => 'smtp.example.com',
                        'port'       => '465',
                        'encryption' => 'ssl',
                        'email'      => 'example@example.com',
                        'password'   => 'yourPassword',
                    ],
                ],
            ],
        ],
    ],
    'forms' => [
        'contact' => [
            'fields' => [
                'name' => [
                    'required' => true,
                ],
                'company' => [
                ],
                'street' => [
                ],
                'city' => [
                ],
                'country' => [
                    'required' => true,
                ],
                'phone' => [
                    'required' => true,
                ],
                'mail' => [
                    'required' => true,
                    'type'     => 'email',
                ],
                'message' => [
                    'required' => true,
                ],
                'somefield' => [
                    'required' => true,
                    'type' => 'csrf'
                ]
            ],
            'adapters' => [
                'globalExampleAdapter-1',
                null
            ],
        ],
        'otherForm' => [
            'fields' => [
                'name' => [
                    'required' => true,
                ],
                'company' => [
                ],
                'street' => [
                ],
                'city' => [
                ],
                'country' => [
                    'required' => false,
                ],
                'phone' => [
                    'required' => true,
                ],
                'mail' => [
                    'required' => true,
                    'type'     => 'email',
                ],
                'message' => [
                    'required' => true,
                ],
                'somefield' => [
                    'required' => true,
                    'type' => 'csrf'
                ]
            ],
            'adapters' => [
                [
                    'method'         => 'phpmail',
                    'reply-to' => [
                        'status' => true,
                        'field'  => 'mail'
                    ],
                    'recipients' => ['example@example.com'],
                    'subject'    => 'example subject',
                    'sender'     => 'sender@example.com',
                    'senderName' => 'Form',
                    'template'       => 'app::test',
                ],
                [
                    'method'         => 'smtpmail',
                    'recipients'     => ['recipient@example.com'],
                    'subject'        => 'base subject all forms that uses this specific adaper has',
                    'sender'         => 'example@example.com',
                    'senderName'     => 'Kontaktformular',
                    'template'       => 'app::test',
                    'email_transfer' => [
                        'config' => [
                            'service'    => 'smtp.example.com',
                            'port'       => '465',
                            'encryption' => 'ssl',
                            'email'      => 'example@example.com',
                            'password'   => 'yourPassword',
                        ],
                    ],
                ],
            ],
        ],
    ],
],

致谢

此捆绑包由designpark开发,并由ElectricBrands分叉。为了在不产生更多混乱的情况下维护此项目,它现在已分叉到我的GitHub上。(实际上,主要是我在开发它)。

许可

MIT许可证(MIT)。有关更多信息,请参阅许可文件