综合演示:MySQL数据库操作
文档概述
本演示文档展示了如何使用轻语言开发一个完整的 Web 应用,包含以下核心功能:
- 用户注册:前端提交账号密码 → 后端 API 接收 → 存入 MySQL
- 用户登录:前端提交凭证 → 后端验证 → 返回登录状态(Session)
- 管理端:查询、模糊查询、修改、删除用户数据
- 安全性:使用 PDO 参数化查询防止 SQL 注入
涉及组件
- 标签、按钮、单行输入框、表格、弹性布局、对话框
- 请求接口、MySQL连接、MySQL查询、MySQL执行、会话凭证
部署要求
- PHP 环境(本地推荐 PhpStudy)
- MySQL 数据库(需提前创建
test数据库和mytable表)
数据库建表语句
-- 建表语句
CREATE TABLE `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`pass` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
接口请求地址
前端通过 请求接口 函数调用后端 API,实际 HTTP 请求格式为:
http://你的域名/User.php?a=注册账号
http://你的域名/Admin.php?a=查询所有用户
💡 参数
a指定要调用的后端函数名。
网站访问地址
-
用户端
-
http://域名.com/
-
http://localhost:1996/index.html
-
子级目录:http://localhost/mywebsite/
-
-
管理端
-
http://域名.com/index.html?admin
-
http://localhost:1996/index.html?admin
-
子级目录:http://localhost/mywebsite/index.html?admin
-
MySQL相关操作函数
本演示文档使用的 MySQL 操作函数(如 MySQL连接、MySQL查询、MySQL执行 等)的详细说明和参数列表,请参考专门的文档:服务端(PHP)函数_MYSQL操作.md。
以下为完整项目代码:
用户端
用户注册登录页面.spldg
<?xml version="1.0" encoding="utf-8"?>
<页面 标题="用户注册登录" 宽度="440" 高度="270">
<绝对布局 名称="根布局">
<标签 名称="标签1" 左边="12" 顶边="12" 高度="40" 宽度="498" 文本="注册/登录账号" 字体大小="24px" />
<按钮 名称="按钮1" 左边="12" 宽度="128" 顶边="150" 高度="40" 文本="注册账号" 文本颜色="#ff0089" />
<单行输入框 名称="单行输入框1" 左边="12" 顶边="58" 高度="40" 宽度="288" 提示文本="请输入账号" />
<单行输入框 名称="单行输入框2" 宽度="288" 高度="40" 左边="12" 顶边="104" 提示文本="请输入密码" />
<按钮 名称="按钮2" 宽度="128" 高度="40" 左边="172" 顶边="150" 文本="登录账号" />
<标签 名称="标签2" 左边="14" 顶边="204" 高度="25" 宽度="166" 文本="登录状态?" 背景颜色="#BFE8FB" />
<标签 名称="标签3" 宽度="99" 高度="25" 左边="201" 顶边="204" 文本="退出" 文本颜色="#FF0000" 光标样式="pointer" 背景颜色="#BFE8FB" />
</绝对布局>
</页面>
用户注册登录页面.spl
' ****************************************************************************
' 版权说明:Copyright(C) All Rights Reserved VcnStudio
' 程序版本:V1.0
' 文件描述:
' 修改日志:
' ****************************************************************************
' 页面变量,整个页面都能使用
变量 页面变量 = "新页面"
事件 页面加载完毕()
' 设置输入框2的类型为:输入密码模式
单行输入框2.类型 = "password"
' 检测登录状态
刷新登录状态()
结束 事件
事件 按钮1.被单击(源对象,事件源)
如果(单行输入框1.内容 == "" 或 单行输入框2.内容 == "")
信息框("账号与密码不能为空!")
返回
结束 如果
变量 待提交数据 = "username=" + 单行输入框1.内容 + "&password=" + 单行输入框2.内容
' 调试输出("待提交数据:" + 待提交数据)
请求接口("User","注册账号",(请求结果,标记)=>{
' 这里返回的请求结果为后端我们的接口函数返回的内容
调试输出(请求结果)
如果(请求结果 == "")
信息框("请求失败!")
返回
结束 如果
' 由于我们后端返回的为 JSON 字符串,这里我们将其转换为 JSON 对象
变量 jsonObj = JSON解析(请求结果)
信息框("返回结果:" + jsonObj.msg + ",状态码:" + jsonObj.code)
},待提交数据)
'* ==============================================================================
'* 部分朋友可能会有个疑问:
'* 为什么这里不能像安卓那样使用直链操作数据库?
'* 答:
'* 如果使用直链数据库操作,网页右键查看源代码、您的数据库账号密码就全部暴露了,
'* 这种方式无异于是告诉任何人您的数据库账号密码,因此任何人都能连接操作。
'* 使用后端接口操作数据库就可以避免这个问题,因为后端接口代码是运行在服务器上面的
'* 右键查看网页源码,无法查看到后端代码,因此采用这种方式是比较安全的。
'* ==============================================================================
结束 事件
事件 按钮2.被单击(源对象,事件源)
如果(单行输入框1.内容 == "" 或 单行输入框2.内容 == "")
信息框("账号与密码不能为空!")
返回
结束 如果
变量 待提交数据 = "username=" + 单行输入框1.内容 + "&password=" + 单行输入框2.内容
请求接口("User","登录账号",(请求结果,标记)=>{
调试输出(请求结果)
如果(请求结果 == "")
信息框("请求失败!")
返回
结束 如果
变量 jsonObj = JSON解析(请求结果)
如果(jsonObj.code == 100)
弹出提示("账号登录成功")
刷新登录状态()
否则
弹出提示(jsonObj.msg)
结束 如果
},待提交数据)
结束 事件
函数 刷新登录状态()
请求接口("User","取登录状态",(请求结果,标记)=>{
如果(请求结果 == "")
返回
结束 如果
调试输出(请求结果)
变量 jsonObj = JSON解析(请求结果)
如果(jsonObj.code == 100)
标签2.文本 = "欢迎回来:" + jsonObj.msg
否则
标签2.文本 = jsonObj.msg
结束 如果
})
结束 函数
事件 标签3.被单击(源对象,事件源)
请求接口("User","退出登录",(请求结果,标记)=>{
刷新登录状态()
})
结束 事件
用户注册登录页面对应的服务器脚本程序文件:User.sph
' ****************************************************************************
' 版权说明:Copyright(C) All Rights Reserved VcnStudio
' 程序版本:V1.0
' 程序作者:
' 联系信息:
' 文件描述:API 接口文件、运行在服务器中;服务器需安装PHP环境、可用于
' 在服务器端操作数据库、接收前端APP、软件、网站或小程序提交
' 的请求;编译时将输出为标准PHP脚本文件。
' 本文件在前端访问时的地址:
' http://你的域名/Api.php?a=待调用函数名称
' 注意事项:
' 1、API 文件中的函数都为全局函数;多个API文件中不能存在相同名称的函数,建议命名为:API接口文件名_函数名
' 2、如果服务器目录存在二级目录、域名中也需要带上二级目录,例如:http://你的域名/二级目录/Api.php?a=待调用函数名称
' 3、API 文件运行时需要服务器安装 PHP 环境的支持;本地开发时可以使用 PhpStudy2018
' 4、如果核心库没有相关中文函数,在代码中可以直接使用PHP原始英文函数
' ****************************************************************************
' 开启 Session 记录用户登录状态
启用会话凭证()
' 向客户端发送服务器的响应报头(Response Header),一般保持默认即可
置响应头("Content-Type: text/html; charset=utf-8")
置响应头("Content-Language: zh-CN")
' 引用轻语言封装的PHP核心库,注:如果要删除该引用请确保当前文件中未使用轻语言封装的函数
引用 "library/qing.core.php"
' 连接数据库,参数分别为:地址,数据库名称,数据库账号,数据库密码
MySQL连接("localhost","test","root","root")
' 调用主函数:“文件被访问”、即当在任何前端中访问该文件时,地址中不带任何参数名,都将会先调用该函数
文件被访问()
' 入口函数,函数名可自定义命名,主要作用:
' 当本文件被访问时,获取其前端传来的请求参数值,根据请求参数值调用当前文件中的函数
函数 文件被访问()
' 通过URL中的键参获取要执行的函数,这里我们默认规定键名为“a”,例如:
' 前端请求地址为:http://xxx.com/本文件名.php?a=测试输出
' 其“a”后面的值“测试输出”即为我们要执行的函数,使用“取请求值”函数将其取出后,然后执行。
变量 待执行函数名 = 取请求值("a")
如果(为空(待执行函数名))
输出 "待执行函数不能为空"
否则
' 增加安全验证,只允许执行我们定义的函数,当然不加也可以,这里仅作标准开发演示
变量 可被执行的函数列表 = [ "注册账号", "登录账号" ,"取登录状态","退出登录"]
如果(取成员是否存在(待执行函数名,可被执行的函数列表) == 真)
输出 执行函数(待执行函数名)
否则
输出 "请求执行非法的函数"
结束 如果
结束 如果
结束 函数
' 前端请求注册账号
函数 注册账号()
' 注意:调用该函数之前,您需要提前在您的数据库中创建一个表,
' 表中至少包含2个字段:name,pass
' 然后在该函数中接收前端传来的数据值
变量 userName = 取请求值("username")
变量 passWord = 取请求值("password")
' 检测一下,提交的请求值是否为空值
如果(为空(userName))
返回 格式化内容(1,"账号不能为空")
结束 如果
如果(为空(passWord))
返回 格式化内容(1,"密码不能为空")
结束 如果
' 检测一下,添加的目标账号是否已经存在
如果(MySQL查找("mytable","name = ?",[userName]))
返回 格式化内容(1,"添加的账号:" + userName + "已经存在")
结束 如果
' 如何符合添加要求,则将这些数据添加到一个数组中
变量 待添加数据 = [userName,passWord]
' 然后构建SQL语句、这里需要注意:由于内置的 MySQL 操作函数采用了PDO方式(防注入)
' 因此这里的SQL语句可能和大家平常在网上看到那种不一样,具体格式为:
变量 SQL命令 = "insert into mytable(name,pass)value(?,?)"
' mytable 为数据库中的表名
' mytable 后面括号的内容为数据表中的字段
' value 后面括号为表中字段对应要添加的占位符
' 规定:第一个括号里面有几个字段,value后面就要添加几个 ? 作为占位符
' 而我们待添加的数据成员长度(数组个数)也必须与字段数量完全一致
' 例如:
' 上述我们要添加 2 个值,那么待添加的数据数组长度也必须为 2 个
' 上述准备工作做好后,就可以开始向数据库中添加数据了
' 如果 MySQL执行 函数执行成功,返回真、否则返回假
如果(MySQL执行(SQL命令,待添加数据))
返回 格式化内容(0,"数据添加成功")
否则
返回 格式化内容(1,"数据添加失败")
结束 如果
结束 函数
函数 登录账号()
' 登录账号的实现逻辑:
' 使用前端提交的请求值查询数据表中是否存在指定记录,如果存在且与提交数据匹配
' 则保护登录状态,返回给前端登录成功
变量 userName = 取请求值("username")
变量 passWord = 取请求值("password")
' 检测一下,提交的请求值是否为空值
如果(为空(userName) 或 为空(passWord))
返回 格式化内容(1,"账号或密码不能为空")
结束 如果
' 查询表中是否存在符合请求值的记录
变量 查询结果 = MySQL取一行("mytable","name=? and pass=?",[userName,passWord])
如果(为空(查询结果) 或 取数组成员数(查询结果) == 0)
返回 格式化内容(1,"账号或密码不正确!")
结束 如果
' 否则保存登录状态,并返回登录成功
置会话凭证("登录账户",userName)
返回 格式化内容(100,"登录成功!")
结束 函数
函数 取登录状态()
变量 已登录账户 = 取会话凭证("登录账户")
如果(已登录账户 != "")
返回 格式化内容(100,已登录账户)
否则
返回 格式化内容(1,"未登录")
结束 如果
结束 函数
函数 退出登录()
' 删除会话凭证中保存的:登录账户 相关数据
销毁会话凭证()
结束 函数
管理端
管理页面.spldg
<?xml version="1.0" encoding="utf-8"?>
<页面 标题="后台管理" 宽度="819" 高度="478">
<绝对布局 名称="根布局">
<按钮 名称="按钮1" 左边="329" 宽度="78" 顶边="18" 高度="31" 文本="查询" />
<表格 名称="表格1" 左边="21" 顶边="55" 高度="346" 宽度="582" />
<单行输入框 名称="单行输入框1" 左边="21" 顶边="18" 高度="31" 宽度="302" 提示文本="请输入待查询用户" />
<按钮 名称="按钮2" 宽度="77" 高度="31" 左边="413" 顶边="18" 文本="模糊查询" />
<按钮 名称="按钮3" 宽度="107" 高度="31" 左边="496" 顶边="18" 文本="获取全部数据" />
<弹性布局 名称="弹性布局1" 左边="628" 顶边="75" 高度="171" 宽度="184">
<单行输入框 名称="单行输入框2" 提示文本="请输入新用户名" />
<单行输入框 名称="单行输入框3" 提示文本="请输入新密码" />
<按钮 名称="按钮_修改" 文本="修改" />
<按钮 名称="按钮_取消修改" 文本="取消" />
</弹性布局>
</绝对布局>
</页面>
管理页面.spl
' ****************************************************************************
' 版权说明:Copyright(C) All Rights Reserved VcnStudio
' 程序版本:V1.0
' 修改日志:
' ****************************************************************************
' 定义当点击编辑标签时显示的弹窗
变量 程_编辑弹窗 = 创建 对话框()
事件 页面加载完毕()
初始化编辑面板弹窗()
' 初始化表头及加载数据
表格1.置表头("ID","账号","密码","操作")
查询所有用户数据()
结束 事件
函数 初始化编辑面板弹窗()
' 弹性布局1 作为对话框面板内容,添加到弹窗
弹性布局1.方向 = "column"
弹性布局1.定位 = ""
程_编辑弹窗.标题 = "编辑信息"
' 调整一下弹性布局中子组件
变量循环(i = 0,弹性布局1.取子组件数(),1)
变量 子对象 = 弹性布局1.取子组件(i)
子对象.外边距 = "5px 0px"
子对象.内边距 = "5px 0px"
结束循环
' 添加给弹窗
程_编辑弹窗.置视图(弹性布局1)
结束 函数
事件 按钮1.被单击(源对象,事件源)
如果(单行输入框1.内容 == "")
弹出提示("请输入待查询用户名称")
返回
结束 如果
变量 待提交数据 = "name=" + 单行输入框1.内容
请求接口("Admin","查询指定用户",(请求结果,标记)=>{
调试输出(请求结果)
如果(请求结果 == "")
弹出提示("查询失败")
返回
结束 如果
表格1.清空()
' 解析并判断是否查询到数据
变量 jsonObj = JSON解析(请求结果)
如果(jsonObj.code == 1)
弹出提示(jsonObj.msg)
返回
结束 如果
' 取出查询到的用户列表
变量 用户列表 = jsonObj.msg
变量循环(i = 0,取数组成员数(用户列表),1)
' 取出列表中每一个用户对象
变量 用户 = 用户列表[i]
' 使用自定义函数创建每一行后面的编辑,删除按钮
变量 局_操作标签 = 创建操作标签(i)
' 然后将用户ID,名称、密码、及操作布局添加到表中
表格1.添加一行(用户.id,用户.name,用户.pass,局_操作标签)
结束循环
},待提交数据)
结束 事件
事件 按钮2.被单击(源对象,事件源)
' 模糊查询与精确查询的代码几乎一样,只是后端的SQL语句不同
如果(单行输入框1.内容 == "")
弹出提示("请输入待查询用户名称")
返回
结束 如果
变量 待提交数据 = "name=" + 单行输入框1.内容
请求接口("Admin","模糊查询指定用户",(请求结果,标记)=>{
调试输出(请求结果)
如果(请求结果 == "")
弹出提示("查询失败")
返回
结束 如果
表格1.清空()
' 解析并判断是否查询到数据
变量 jsonObj = JSON解析(请求结果)
如果(jsonObj.code == 1)
弹出提示(jsonObj.msg)
返回
结束 如果
' 取出查询到的用户列表
变量 用户列表 = jsonObj.msg
变量循环(i = 0,取数组成员数(用户列表),1)
' 取出列表中每一个用户对象
变量 用户 = 用户列表[i]
' 使用自定义函数创建每一行后面的编辑,删除按钮
变量 局_操作标签 = 创建操作标签(i)
' 然后将用户ID,名称、密码、及操作布局添加到表中
表格1.添加一行(用户.id,用户.name,用户.pass,局_操作标签)
结束循环
},待提交数据)
结束 事件
事件 按钮3.被单击(源对象,事件源)
查询所有用户数据()
结束 事件
函数 查询所有用户数据()
表格1.清空()
请求接口("Admin","查询所有用户",(请求结果,标记)=>{
调试输出(请求结果)
如果(请求结果 == "")
返回
结束 如果
变量 jsonObj = JSON解析(请求结果)
' 注意:这里返回的请求结果里面的 msg 值为一个 JSON 数组
变量 用户列表 = jsonObj.msg
变量循环(i = 0,取数组成员数(用户列表),1)
' 取出列表中每一个用户对象
变量 用户 = 用户列表[i]
' 使用自定义函数创建每一行后面的编辑,删除按钮
变量 局_操作标签 = 创建操作标签(i)
' 然后将用户ID,名称、密码、及操作布局添加到表中
表格1.添加一行(用户.id,用户.name,用户.pass,局_操作标签)
结束循环
})
结束 函数
' 将创建操作标签的代码单独封装成一个函数调用
函数 创建操作标签(索引)
' 创建表格中操作栏的 编辑|删除 标签
变量 局_操作布局 = 创建 弹性布局()
局_操作布局.定位 = ""
变量 局_编辑标签 = 创建 标签()
局_编辑标签.定位 = ""
局_编辑标签.文本 = "编辑"
局_编辑标签.文本颜色 = "#006cd7"
局_编辑标签.光标样式 = "pointer"
局_编辑标签.外边距右 = "10px"
局_编辑标签.置被单击回调(()=>{
' 弹出提示("表项:" + 索引 + "编辑")
' 弹出自定义对话框弹窗,编辑内容
编辑指定用户(索引)
})
变量 局_删除标签 = 创建 标签()
局_删除标签.定位 = ""
局_删除标签.文本 = "删除"
局_删除标签.文本颜色 = "#ff0000"
局_删除标签.光标样式 = "pointer"
局_删除标签.置被单击回调(()=>{
' 根据索引取出表中当前行的数据,再根据列索引取出用户名
变量 目标行 = 表格1.取一行(索引)
调试输出(目标行)
变量 待删除用户名 = 目标行[1]
删除数据表用户(待删除用户名)
})
' 将编辑、删除标签添加到操作布局中
局_操作布局.添加组件(局_编辑标签)
局_操作布局.添加组件(局_删除标签)
' 返回整个操作布局
返回 局_操作布局
结束 函数
函数 删除数据表用户(用户名)
如果(确认框("确定要删除“" + 用户名 + "”吗?") == 真)
' 发送删除请求
请求接口("Admin","删除用户",(请求结果,标记)=>{
如果(请求结果 == "")
信息框("发送删除请求失败")
返回
结束 如果
变量 jsonObj = JSON解析(请求结果)
弹出提示(jsonObj.msg)
如果(jsonObj.code == 100)
' 刷新数据表、查询所有数据
查询所有用户数据()
结束 如果
},"name=" + 用户名)
结束 如果
结束 函数
函数 编辑指定用户(索引)
变量 行数据 = 表格1.取一行(索引)
单行输入框2.内容 = 行数据[1]
单行输入框3.内容 = 行数据[2]
' 注册面板中的按钮事件
按钮_修改.置被单击回调(()=>{
变量 待提交数据 = "id=" + 行数据[0] + "&name=" + 单行输入框2.内容 + "&pass=" + 单行输入框3.内容
'调试输出(待提交数据)
请求接口("Admin","编辑用户",(请求结果,标记)=>{
变量 jRes = JSON解析(请求结果)
弹出提示(jRes.msg)
' 根据后端返回的状态码,判断是否修改成功
如果(jRes.code == 100)
' 刷新数据
查询所有用户数据()
' 关闭弹窗
程_编辑弹窗.关闭()
结束 如果
},待提交数据)
})
按钮_取消修改.置被单击回调(()=>{
程_编辑弹窗.关闭()
})
程_编辑弹窗.显示()
结束 函数
管理页面对应的服务器脚本程序文件:Admin.sph
' ****************************************************************************
' 版权说明:Copyright(C) All Rights Reserved VcnStudio
' 程序版本:V1.0
' 文件描述:管理端接口文件、用于管理,查询、修改、删除表中的数据。
' 修改日志:
' ****************************************************************************
' 开启 Session 记录用户登录状态
启用会话凭证()
' 向客户端发送服务器的响应报头(Response Header)
置响应头("Content-Type: text/html; charset=utf-8")
置响应头("Content-Language: zh-CN")
' 引用轻语言封装的PHP核心库,注:如果要删除该引用请确保当前文件中未使用轻语言封装的函数
引用 "library/qing.core.php"
' 连接数据库,参数分别为:地址,数据库名称,数据库账号,数据库密码;注意:连接数据库操作必须放在引用核心库之后
MySQL连接("localhost","test","root","root")
' 调用主函数:“文件被访问”、即当在任何前端中访问该文件时,地址中不带任何参数名,都将会先调用该函数
文件被访问()
' 入口函数,函数名可自定义命名,主要作用:
' 当本文件被访问时,获取其前端传来的请求参数值,根据请求参数值调用当前文件中的函数
函数 文件被访问()
' 通过URL中的键参获取要执行的函数,这里我们默认规定键名为“a”,例如:
' 前端请求地址为:http://xxx.com/本文件名.php?a=测试输出
' 其“a”后面的值“测试输出”即为我们要执行的函数,使用“取请求值”函数将其取出后,然后执行。
变量 待执行函数名 = 取请求值("a")
如果(为空(待执行函数名))
输出 "待执行函数不能为空"
否则
输出 执行函数(待执行函数名)
结束 如果
结束 函数
函数 查询所有用户()
' 查询表中所有用户数据,返回给前端
变量 查询结果 = MySQL查询("select * from mytable",[])
如果(为空(查询结果))
返回 格式化内容(1,"数据查询失败")
结束 如果
' 查询结果不为空、则将查询结果格式化为JSON数据格式值返回给前端
返回 格式化内容(0,查询结果)
结束 函数
函数 查询指定用户()
变量 name = 取请求值("name")
如果(为空(name))
返回 格式化内容(1,"待查询用户名不能为空")
结束 如果
变量 查询结果 = MySQL查询("select * from mytable where name=?",[name])
如果(为空(查询结果))
返回 格式化内容(1,"未查询到用户名为:" + name + " 的用户")
结束 如果
返回 格式化内容(0,查询结果)
结束 函数
函数 模糊查询指定用户()
变量 name = 取请求值("name")
如果(为空(name))
返回 格式化内容(1,"待查询用户名不能为空")
结束 如果
' 模糊查询核心改动:
' name = ? 修改为 like ?
' 且待查询的关键字两边必须加上 % %
变量 待查询账号 = "%" + name + "%"
变量 查询结果 = MySQL查询("select * from mytable where name like ?",[待查询账号])
如果(为空(查询结果))
返回 格式化内容(1,"未查询到用户名为:" + name + " 的用户")
结束 如果
返回 格式化内容(0,查询结果)
结束 函数
函数 删除用户()
' 根据前端传来的条件值删除用户,这里我们仍然根据用户名进行删除
变量 name = 取请求值("name")
如果(为空(name))
返回 格式化内容(1,"待删除用户名不能为空")
结束 如果
变量 SQL命令 = "delete from mytable where name = ?"
如果(MySQL执行(SQL命令,[name]))
返回 格式化内容(100,"用户删除成功")
否则
返回 格式化内容(1,"用户删除失败")
结束 如果
结束 函数
函数 编辑用户()
变量 id = 取请求值("id")
变量 name = 取请求值("name")
变量 pass = 取请求值("pass")
如果(为空(id) 或 为空(name) 或 为空(pass))
返回 格式化内容(1,"待修改内容不能为空数据")
结束 如果
变量 SQL命令 = "update mytable set name=?,pass=? where id=?"
如果(MySQL执行(SQL命令,[name,pass,id]))
返回 格式化内容(100,"用户数据修改成功")
否则
返回 格式化内容(1,"用户数据修改失败")
结束 如果
结束 函数
学习要点
通过本综合演示,你可以学习到以下轻语言全栈开发技术:
| 知识点 | 代码位置 | 说明 |
|---|---|---|
| MySQL连接初始化 | MySQL连接("localhost","test","root","root") | 在 .sph 文件中初始化数据库连接,必须放在 引用 "library/qing.core.php" 之后 |
| PDO 参数化查询 | MySQL执行(SQL命令,[userName,passWord]) | 使用 ? 占位符 + 数组传参,从根本上防止 SQL 注入 |
| 模糊查询 | "select * from mytable where name like ?" | SQL 中将 = 改为 like,并在参数两侧拼接 % 实现模糊搜索 |
| 会话凭证管理 | 启用会话凭证、置会话凭证、取会话凭证、销毁会话凭证 | 通过 Session 实现"登录状态"在前后端之间的传递与保持 |
| 接口函数白名单 | 可被执行的函数列表 = [ "注册账号", "登录账号" , ...] | 防止前端通过 URL 任意调用任意函数,提升 API 安全性 |
| 前端请求接口 | 请求接口("User","注册账号",回调,待提交数据) | 前端通过接口名调用后端函数,由框架自动转换为 HTTP 请求并解析响应 |
| JSON 数据交换 | 格式化内容(状态码,数据) ↔ JSON解析(请求结果) | 后端统一返回 {code,msg} 结构,前端解析后按 code 分支处理 |
| 动态表格渲染 | 表格1.添加一行(用户.id,用户.name,用户.pass,局_操作标签) | 在循环中将每行数据 + 操作按钮布局一同塞入表格 |
| 自定义组件创建 | 创建 弹性布局、创建 标签、置被单击回调 | 在普通函数中动态创建组件并绑定事件回调 |
| 对话框弹窗 | 创建 对话框、置视图(弹性布局1)、显示、关闭 | 将布局作为对话框内容视图,实现自定义编辑面板 |
安全最佳实践
本演示遵循了以下安全开发规范,请在实际项目中同样遵守:
- 永远不要在前端代码中直连数据库:网页右键查看源代码会暴露数据库账号密码。所有数据库操作必须通过后端
.sph接口完成。 - 永远使用 PDO 参数化查询:禁止使用字符串拼接构造 SQL,必须使用
?占位符 + 数组传参的形式(如MySQL执行(SQL命令,[name,pass]))。 - API 函数白名单:在
文件被访问入口函数中限制可调用的函数名,拒绝前端传入未定义的函数名。 - 空值校验:在接口函数开头使用
为空()检测必填字段,返回明确的错误信息。 - 唯一性校验:注册前使用
MySQL查找检测账号是否已存在,避免重复注册。 - 会话过期处理:使用
销毁会话凭证()实现安全退出,避免长期持有失效登录态。
扩展方向
你可以基于本演示继续扩展以下功能:
- 密码加密:使用
md5()或更安全的password_hash()(PHP 原生函数)对密码进行加密存储 - 权限分级:在
mytable表中新增role字段,区分普通用户和管理员,在.sph中根据 role 限制可调用的接口 - 分页查询:使用 SQL 的
LIMIT子句实现分页,前端通过表格的"上一页 / 下一页"按钮请求不同页 - 数据导出:将查询结果通过
JSON编码或 CSV 格式导出,提供"下载用户列表"功能 - 登录验证码:集成第三方滑动验证码或图形验证码,防止暴力破解
- 操作日志:在每次 CRUD 操作时,将操作人、操作时间、操作内容写入
log表,实现审计
💡 相关文档:本演示中使用的 MySQL 操作函数(
MySQL连接、MySQL查询、MySQL执行等)详细参数说明请参考文档服务端(PHP)函数_MYSQL操作;前端请求接口函数用法请参考文档轻语言网站:发送网络请求与接口请求;.sph接口文件结构请参考文档轻语言网站:服务端脚本程序API接口;界面 XML 标签和属性定义请参考文档轻语言网站:界面XML定义规范。