Symfony 验证
最后修改于 2020 年 7 月 5 日
Symfony 验证教程展示了如何在 Symfony 应用程序中验证数据。在本教程中,我们使用手动验证。我们不使用 doctrine 注解。
Symfony
Symfony 是一组可重用的 PHP 组件和一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年作为自由软件发布。Symfony 的原始作者是 Fabien Potencier。Symfony 的灵感来自 Ruby on Rails、Djanog 和 Spring Framework。
Symfony 验证
必须验证来自用户的输入。Symfony 提供了一个 Validator 组件来执行验证任务。该组件基于 Java 的 Bean Validation 规范。
Validator 旨在针对约束验证对象。约束是断言一个条件为真的断言。Symfony 包含许多内置约束,包括 NotBlank、Email、Length 和 Isbn。也可以创建自定义约束。
Symfony 验证示例
在示例中,我们有一个包含两个字段的简单表单:name 和 email。提交表单后,我们使用 Symfony 的 Validator 手动验证字段。在示例中,我们使用了 Length、NotBlank 和 Email 约束。
安装软件包
$ composer create-project symfony/skeleton myval $ cd myval
我们创建一个新的 Symfony 项目并进入项目目录。
$ composer req maker server --dev
我们安装 symfony/maker-bundle 和 symfony/web-server-bundle。这些对于开发模式很有用。请注意,我们使用的是软件包的别名。
$ composer req twig annotations
我们安装 twig-bundle 和注解。注解位于 sensio/framework-extra-bundle。
$ composer req validator
symfony/validator 包包含 Symfony 验证工具。
$ composer req security-csrf $ composer req monolog $ composer req property-access
symfony/security-csrf 包对于防止跨站请求伪造是必需的,symfony/monolog-bundle 用于日志记录,symfony/property-access 用于操作 PHP 属性。
构建 Symfony 应用程序
$ php bin/console make:controller HomeController
我们创建一个 HomeController。
<?php
namespace App\Controller;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class HomeController extends AbstractController
{
/**
* @Route("/home", name="home")
*/
public function index(): Response
{
return $this->render('home/index.html.twig');
}
}
这是一个简单的控制器,它将包含 Web 表单的视图发送给用户。
$ php bin/console make:controller FormController
我们创建一个 FormController 来响应表单提交。
<?php
namespace App\Controller;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class FormController extends AbstractController
{
/**
* @Route("/sendForm", name="form")
*/
public function index(Request $request, ValidatorInterface $validator,
LoggerInterface $logger): Response {
$token = $request->request->get("token");
if (!$this->isCsrfTokenValid('myform', $token)) {
$logger->info("CSRF failure");
return new Response("Operation not allowed", Response::HTTP_OK,
['content-type' => 'text/plain']);
}
$name = $request->request->get("name");
$email = $request->request->get("email");
$input = ['name' => $name, 'email' => $email];
$constraints = new Assert\Collection([
'name' => [new Assert\Length(['min' => 2]), new Assert\NotBlank],
'email' => [new Assert\Email(), new Assert\notBlank],
]);
$violations = $validator->validate($input, $constraints);
if (count($violations) > 0) {
$accessor = PropertyAccess::createPropertyAccessor();
$errorMessages = [];
foreach ($violations as $violation) {
$accessor->setValue($errorMessages,
$violation->getPropertyPath(),
$violation->getMessage());
}
return $this->render('form/violations.html.twig',
['errorMessages' => $errorMessages]);
} else {
return new Response("Validation passed", Response::HTTP_OK,
['content-type' => 'text/plain']);
}
}
}
在 FormController 中,我们检查 CSRF 令牌,验证表单输入值,并将响应发送回客户端。
注意: 出于简单性考虑,我们将验证代码放在了控制器中。在生产应用程序中,最好将此类代码放在单独的服务类中。
public function index(Request $request, ValidatorInterface $validator,
LoggerInterface $logger)
{
我们注入请求对象、验证器对象和日志记录器对象。
$token = $request->request->get("token");
if (!$this->isCsrfTokenValid('myform', $token)) {
$logger->info("CSRF failure");
return new Response("Operation not allowed", Response::HTTP_OK,
['content-type' => 'text/plain']);
}
我们检索令牌并使用 isCsrfTokenValid() 方法进行验证。
$name = $request->request->get("name");
$email = $request->request->get("email");
$input = ['name' => $name, 'email' => $email];
我们获取请求输入参数并将其放入一个数组中。
$constraints = new Assert\Collection([
'name' => [new Assert\Length(['min' => 2]), new Assert\NotBlank],
'email' => [new Assert\Email(), new Assert\notBlank]
]);
我们创建一个约束集合。我们可以为单个值分配多个约束。
$violations = $validator->validate($input, $constraints);
我们使用 validate() 方法根据约束验证输入数据。该方法返回可能的违规。Symfony 验证器返回一个 ConstraintViolationList。我们使用 Symfony accessor 来处理列表。
if (count($violations) > 0) {
我们检查是否有一些违规。
$accessor = PropertyAccess::createPropertyAccessor();
$errorMessages = [];
foreach ($violations as $violation) {
$accessor->setValue($errorMessages,
$violation->getPropertyPath(),
$violation->getMessage());
}
Symfony PropertyAccess 用于在将违反消息发送到模板之前进行处理。ConstraintViolationList 被转换为 PHP 数组,其中键是表单字段,值是错误消息。该数组稍后在 Twig 中使用 for 指令进行处理。
return $this->render('form/violations.html.twig',
['errorMessages' => $errorMessages]);
我们将错误消息渲染在单独的页面上。这通常使用 flash 消息完成。请参阅 Symfony 保留表单值教程 了解如何使用 flashes 实现。
} else {
return new Response("Validation passed", Response::HTTP_OK,
['content-type' => 'text/plain']);
}
如果一切正常,我们发送一条纯消息验证通过。
{% extends 'base.html.twig' %}
{% block title %}Home page{% endblock %}
{% block body %}
<form action="sendForm" method="post">
<input type="hidden" name="token" value="{{ csrf_token('myform') }}" />
<div>
<label>Name:</label>
<input type="text" name="name">
</div>
<div>
<label>Email</label>
<input type="email" name="email">
</div>
<button type="submit">Send</button>
</form>
{% endblock %}
表单包含两个字段:姓名和电子邮件。
<input type="hidden" name="token" value="{{ csrf_token('myform') }}" />
它还包含一个隐藏字段以防止跨站请求伪造。
{% extends 'base.html.twig' %}
{% block title %}Violations{% endblock %}
{% block body %}
<h2>Validation failed</h2>
<ul>
{% for field, errorMessage in errorMessages %}
<li>{{ field }}: {{ errorMessage }}</li>
{% endfor %}
</ul>
{% endblock %}
在 violations 视图中,我们遍历违规并列出它们。
{% for field, errorMessage in errorMessages %}
<li>{{ field }}: {{ errorMessage }}</li>
{% endfor %}
使用 for 指令,我们遍历错误消息并在存在时显示它们。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
</html>
这是基本的 Twig 模板。
$ php bin/console server:run
我们启动开发服务器。然后定位到 localhost:8000/home URL 来获取表单。
在本教程中,我们在 Symfony 应用程序中验证了一个简单的表单。我们使用了手动验证。