PHP 后端表单验证和请求处理
创建好前端的联系表单视图后,接下来,我们来编写提交表单后后端的 PHP 处理逻辑。
数据表和模型类
我们会将用户提交的请求数据保存到 messages
表中,所以我们需要在数据库中新增这张数据表:
--
-- 数据库: `blog`
--
-- --------------------------------------------------------
--
-- 表的结构 `messages`
--
CREATE TABLE `messages` (
`id` int UNSIGNED NOT NULL,
`name` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
`email` varchar(100) COLLATE utf8mb4_general_ci NOT NULL,
`phone` varchar(20) COLLATE utf8mb4_general_ci NOT NULL,
`content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`created_at` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='消息表';
然后在 blog
项目的 app/model
目录下新建对应的模型类 Message
:
<?php
namespace AppModel;
use IlluminateDatabaseEloquentModel;
class Message extends Model
{
public $timestamps = false;
}
表单数据处理逻辑
做好上述准备后,接下来,我们在 HomeController
控制器的 contact
方法中,编写表单数据获取、验证和保存代码:
public function contact()
{
if ($this->request->getMethod() == 'GET') {
// 联系表单页面
...
} else {
// POST 提交表单处理逻辑
$name = $this->request->get('name');
$email = $this->request->get('email');
$phone = $this->request->get('phone');
$content = $this->request->get('message');
// 验证表单输入数据
if (empty($name)) {
throw new ValidationException('用户名不能为空');
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new ValidationException('请输入正确的邮箱地址');
}
if (!preg_match('/^1[34578]{1}d{9}$/', $phone)) {
throw new ValidationException('请输入正确的手机号码');
}
if (empty($content)) {
throw new ValidationException('消息内容不能为空');
}
$message = new Message();
$message->name = filter_var($name, FILTER_SANITIZE_STRING);
$message->email = $email;
$message->phone = $phone;
$message->content = filter_var($content, FILTER_SANITIZE_STRING);
$message->created_at = Carbon::now();
if ($message->save()) {
(new Response('消息保存成功', 200))->send();
}
(new Response('保存消息失败,请重试!', 500))->send();
}
}
这里,我们通过 $this->request->get
方法获取表单请求数据,然后对这些表单数据进行简单的验证,比如用户名和消息内容不能为空、邮箱格式必须合法(使用 PHP 内置的 filter_var 方法进行过滤,该方法通过传入的第二个验证过滤器常量参数对变量值进行验证,还可以支持 IP、URL 等其他字符串格式的校验)、手机号符合正则匹配规则,如果验证不通过会抛出 ValidationException
异常,关于异常响应的处理,我们稍后会介绍。
如果所有请求数据通过验证,就可以通过 Message
模型类实例将其保存到数据库中了。这里,对于用户名和消息内容,我们还调用了 filter_var
方法,并在第二个参数传入「消毒」过滤器常量参数对其进行处理,以避免字符串中包含 HTML 标签,出现 XSS 攻击隐患。
因此,
filter_var
函数可以根据传入的第二个参数标识进行不同的操作,既可以用于字段验证,也可以用作消毒处理,还可以通过回调函数进行额外的自定义操作,更多细节请参考 PHP 官方文档关于该函数的介绍。
消息保存成功后,我们通过 Response
对象发送响应给客户端。
异常响应处理
在测试表单请求处理逻辑之前,我们来介绍下对异常响应的处理。
在上面的代码中,当请求字段验证失败后,会抛出 ValidationException
异常(该异常类定义在 app/http/exception
目录下):
<?php
namespace AppHttpException;
class ValidationException extends Exception
{
}
此时,程序就终止了,不能继续往后执行了,那么这种情况下该如何将异常信息发送给客户端呢?
这里,我们可以借助之前在 PHP 错误和异常处理教程中介绍的全局异常处理器来捕获程序中抛出的所有未处理异常,进行兜底处理。
打开 app/bootstrap.php
文件,在里面定义一个注册全局异常处理器的方法:
// 注册全局异常处理器
function registerExceptionHandler()
{
set_exception_handler(function ($exception) {
$response = new Response();
if ($exception instanceof ValidationException) {
$response->setStatusCode(422);
$response->setContent($exception->getMessage());
} else {
$response->setStatusCode(500);
$response->setContent( '服务器异常');
}
$response->send();
});
}
我们通过 set_exception_handler
注册全局异常处理器,在定义异常处理逻辑的回调函数中,可以看到,如果捕获到的异常是 ValidationException
实例,则将响应状态码设置为 422
,然后通过 Response
响应实例发送验证错误信息给客户端,对于其他异常,目前先统一返回 500
错误。
最后在启动应用的 bootApp
方法中,调用这个注册全局异常处理器的 registerExceptionHandler
方法即可:
/**
* 启动应用
* @param Container $container
* @return Container
*/
function bootApp(Container $container)
{
registerExceptionHandler();
...
}
在联系表单页面发起请求
至此,我们就完成了 POST 表单请求的所有后端处理逻辑,在浏览器打开联系表单页面,如果输入了错误的手机号,会返回对应的验证错误消息:
如果所有表单数据都通过验证,则会看到消息发送成功提示:
当然,这里还有可以优化的地方,比如,在请求数据验证失败后,返回提交的请求数据填充对应的输入框,以免用户重新输入。
访问数据库,在 messages
表中应该可以看到最新插入的记录:
这样,完整的前后端表单请求功能就完成了,博客前端功能也就告一段落了,下篇教程,学院君会给大家如何纯手工搭建博客后台管理系统。
(全文完)
- 使用root用户连接Ubuntu16.04时,提示SSH连接被拒绝
- CSS魔法堂:Box-Shadow没那么简单啦:)
- java操作redis: 将string、list、map、自定义的对象保存到redis中
- 运行第一个Docker容器-Docker for Web Developers(1)
- 手动实现jQuery Tools里面tab功能
- Angular企业级开发(9)-前后端分离之后添加验证码
- 基于thrift的微服务框架
- Sublime Text 快速格式化
- HTML中拖放介绍
- 打造高效前端工作环境 - tmux
- 基于thrift的微服务框架
- thrift中的超时(timeout)坑
- 基于webmagic的爬虫项目经验小结
- Docker Hub工作流程-Docker for Web Developers(6)
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- Android自定义双向进度条的实现代码
- android视频截屏&手机录屏实现代码
- Android自定义组件跟随自己手指主动画圆
- Android RecyclerView 实现快速滚动的示例代码
- Android的八种对话框的实现代码示例
- Android使用RecyclerView实现今日头条频道管理功能
- Liunx(centos8)下的yum的基本用法和实例(推荐)
- Android中LeakCanary检测内存泄漏的方法
- Linux 查看磁盘IO并找出占用IO读写很高的进程
- Android实现简单的拨号器功能
- Android调用系统自带浏览器打开网页的实现方法
- Linux之删除带有空格的文件(不是目录)
- Android自定义AvatarImageView实现头像显示效果
- 如何使用win10内置的linux系统启动spring-boot项目
- Android 实现单线程轮循机制批量下载图片