json() 提供 方法
修改 开启报错查看
![](https://img.kancloud.cn/0c/90/0c9007f59b7ad18eeefe50fc4238e4ff_196x109.png)
## env
中开启 de\_bug
database配置数据库 会先使用 .env 中的配置!
![](https://img.kancloud.cn/ee/ad/eead3bc36f4c4c5fafb7666be0f5d46c_885x660.png)
![](https://img.kancloud.cn/39/95/399564537aa41bef8a6697a4a2fd28c8_459x495.png)
tp6 中使用
**Db**:: 需要 use 门面模式 user think\\facade/\\Db
![](https://img.kancloud.cn/b5/7c/b57cde7c1e3dd0ba472045914387d9b9_1073x294.png)
## app.php
config/app.php 错误信息
## 多应用模式
```
composer require topthink/think-multi-app
```
在当前控制器下创建 route 路由文件夹
配置域名访问
http://www.tp6.com/demo.php/index/test?a=1
在public 下复制index.php 改名为 demo.php
$response = $http->name(‘demo’)->run(); 若是文件名不同 可用 name指向
config 可以在每个 目录下 +
admin / config 当前目录有用
api/config …
## 路由
多应用 需要 加 文件名 admin/text index/…
## config 下 业务状态码
创建 status.php`
return \[
‘success’ => 1,
‘error’ => 0,
\];
未开启强制路由
都可以
http://www.tp6.com/index.php/demo/index/t demo 应用 inde想控制器 t方法
http://www.tp6.com/demo.php/index/t
![](https://img.kancloud.cn/b7/07/b707c6984f257935eca4e4625cfe7788_1018x521.png)
![](https://img.kancloud.cn/2a/42/2a42dbffa035fae58125f5760e476801_926x407.png)
## has 判断某个值是否设置
## 容器和依赖注入
![](https://img.kancloud.cn/3b/5a/3b5a3ab7606f10135a50ec4d200454c0_654x276.png)
![](https://img.kancloud.cn/d4/b7/d4b7603cc4f8e8488f67df688518e459_368x390.png)
## 全局中间件
可以通过命令行指令快速生成中间件
php think make:middleware Check
~~~
<?php
namespace app\middleware;
class Check
{
public function handle($request, \Closure $next)
{
// 添加中间件执行代码
...
return $next($request);
}
}
~~~
在 app/middleware.php
~~~
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class
app\middleware\Check::class,
];
~~~
## 应用中间件
![](https://img.kancloud.cn/89/f2/89f28316c52f626c45143d902170f7b8_302x378.png)
## 模板引擎
composer安装
![](https://img.kancloud.cn/1e/ad/1eadbadf346ddd4716c0c47f6de043e3_1106x700.png)
```
composer require topthink/think-view
```
## 简单的密码+盐处理
密码 123
md5(‘123\_md5’) 处理字符串
## 验证码
```
composer require topthink/think-captcha
```
![](https://img.kancloud.cn/a0/aa/a0aa90a524ece726e29d54f48b01bb8b_1851x1080.png)
![](https://img.kancloud.cn/4e/9e/4e9ed419d414fdb8f7bf8a78f927f6f0_1089x236.png)
验证码使用 验证是时 徐快需要在中间件中开启session!
![](https://img.kancloud.cn/54/3e/543eac0212132ea796af2bdc73167085_1851x1080.png)
## 模型分层架构
![](https://img.kancloud.cn/12/78/1278c00aeef4e02ce8fd4937ef5a0c1d_1306x521.png)
思维
## 验证器
~~~
$data = [
'username' => $username,
'password' => $password,
'captcha' => $captcha,
];
$validate = new \app\admin\validate\AdminUser();
if(!$validate->check($data)) {
return show(config("status.error"), $validate->getError());
}
~~~
~~~
<?php
/**
* Created by singwa
* User: singwa
* motto: 现在的努力是为了小时候吹过的牛逼!
* Time: 07:11
*/
namespace app\admin\validate;
use think\Validate;
class AdminUser extends Validate {
protected $rule = [
'username' => 'require',
'password' => 'require',
'captcha' => 'require|checkCapcha',
];
protected $message = [
'username' => '用户名必须,请重新输入',
'password' => '密码必须',
'captcha' => '验证码必须',
];
protected function checkCapcha($value, $rule, $data = []) {
if(!captcha_check($value)) {
return "您输入的验证码不正确!";
}
return true;
}
}
~~~
## Url 注意
![](https://img.kancloud.cn/e6/15/e615c34cdf3dfbc35db4ea0d9f62b741_557x165.png)
## 如何正确分层之操作datebase
## 注意使用 init初始化
## 如何处理在init里无法重定向
![](https://img.kancloud.cn/83/c0/83c0606e76437160937177719eea752b_1851x1080.png)
## 注意 如何 /admin/index/index 写的时候需要+ /’
## 前置中间件
![](https://img.kancloud.cn/4d/de/4ddedaf37985db4e6bbaab15ad8689f7_1851x1080.png)
preg\_match()
1 正则
2 str 匹配2中有无 1
return 1 0
## 后置中间件
![](https://img.kancloud.cn/f9/10/f910186efb51f5a31788f97233776d80_789x735.png)
## session
~~~
session('adminUser', $res); session('adminUser', null);
~~~
* 1
## business 业务逻辑层
在business 处理业务逻辑 -> 调用 model 的sql执行 在business进行 异常抛出 在c层try catch 补获
model 放在 common 公共文件里
![](https://img.kancloud.cn/d8/be/d8be27a60a09cb14a946e5b53725a2fd_1851x1080.png)
## redis 实现验证码 存活时间60s
安装 https://blog.csdn.net/kxukai/article/details/106692983
## 日志
开启日志 runtime 可以查看执行的原生sql语句 进行分析
![![](https://img.kancloud.cn/d8/be/d8be27a60a09cb14a946e5b53725a2fd_1851x1080.png)](images/screenshot_1653443315790.png)
## 工厂模式
![](https://img.kancloud.cn/21/08/2108d204a41d287191e7460f13dcf0cc_1850x1080.png)
![](https://img.kancloud.cn/da/56/da565da7d763838acef7e3260b8f689c_1850x1080.png)
![](https://img.kancloud.cn/23/e1/23e1f0e4616fd9cb9b87d27be00f1346_1850x1080.png)
短信可以使用redis 进行限制 存手机号 + 发信息间隔时间~
## 如何流控 20%阿里云短信 80%百度云短信
案例:2018年年底 央视春晚 百度手机号登录发送验证码分发不同运营商流量, 就是用这个来做的, 并发50万 发送短信验证码。
简单粗暴 实用 最简单的方法往往最有效
~~~
$a = rand(0,99);
if($a < 80) {
// 阿里云逻辑
} else {
// 百度云逻辑
}
~~~
## 前后端分离 redis+ token 不使用session+cookie
## config(‘statis.success’)
![](https://img.kancloud.cn/27/86/278635f2adffa5b34a7b9ca052a25e43_475x395.png)
## 异常处理 try catch
捕获异常时 注意记录日志 以供分析
tp6 helper 全局搜索自带抛出异常 throw\_if 同laravel
手动抛出异常
~~~
throw new \think\Exception("不存在该验证码", config('status.code.not_code'));
~~~
* 1
捕获异常
~~~
try {
$result = (new \app\common\business\User())->login($data);
} catch (\Exception $e) {
return show($e->getCode(), $e->getMessage());
}
~~~
// 阻止数据库抛出异常 被 用户看到 手动抛出~
~~~
try {
$this->userObj->save($userData);
$userId = $this->userObj->id;
}catch (\Exception $e) {
throw new \think\Exception("数据库内部异常");
}
~~~
![](https://img.kancloud.cn/2f/ee/2feece55d1a07376a775a1a7cfffa41a_1851x1080.png)
## redis 删除 等于null 即可
## redis 写登录 逻辑
前后端分离 所以是 api 接口
1. 用户点击发送验证码 把 sms . 手机号 存入 redis 内容有 验证码 存活60s //这里sms为了再redis中进行区分别的缓存
2. 接收数据 转换格式 验证 isajax ispost
~~~
if (!$this->request->isPost() || !$this->request->isAjax() )
return show(config("status.error"), "非法请求");
$phoneNumber = input("phone_number",'','trim');
$code = input("code", 0, "intval");
~~~
3. validate 验证器 验证参数
4. 验证 用户输入的 code !== redis中的该手机号对应的 code
~~~
// 用户输入的 code !== redis中的该手机号对应的 code
$redisCode = cache(config("redis.code_pre") . $data['phone_number']);
if (empty($redisCode) || $redisCode != $data['code']) {
throw new \think\Exception("不存在该验证码", config('status.code.not_code'));
}
~~~
从第五层开始要在 business 逻辑层进行处理 判断
例子 抛出异常最好用 try catch 进行补获 避免数据库抛出暴露信息被用户查看
![](https://img.kancloud.cn/4c/a3/4ca31f6f7c8d6d7e08df08dbf039e87f_1851x1080.png)
5\. 还是在common/ business 操作
根据用户手机号 查找有该用户登录记录
~~~
// 需要去判断表 是否有 用户记录 phone_number
// 生成token
$user = $this->userObj->getUserByPhoneNumber($data['phone_number']);
~~~
这里model 层在 common/model datebase 操作公共的 可以共用
![](https://img.kancloud.cn/f2/b6/f2b618a9d4fb46ea7132573341cce74f_574x296.png)
然后进行判断 操作用户记录
![](https://img.kancloud.cn/a7/14/a71433e0a3f3640d8a3b18f247815495_701x570.png)
6\. 然后把生成的token作为k 用户的id 和用户名作为 v 存入redis 存活时间 ~
~~~
$redisData = [
"id" => $userId,
"username" => $username,
];
$res = cache(config("redis.token_pre") . $token, $redisData, Time::userLoginExpiresTime($data['type']));
~~~
7.最后把前端需要的数据返回
## 中间件 进行 前端 检测是否登录 2种方法
第一种方法 需要验证login的controller extends 该控制器 进行检测
~~~
class AuthBase extends ApiBase
{
public $userId = 0;
public $username = "";
public $accessToken = "";
public $isLogin = 1;
public function initialize()
{
parent::initialize(); // TODO: Change the autogenerated stub
// if ($this->isLogin == 1) {
// $this->userId = 6; // 测试场景
// return true;
// }
$this->accessToken = $this->request->header("access-token");
if (!$this->accessToken || !$this->isLogin()) {
return $this->show(config("status.not_login"), "没有登录");
}
}
/**
* 判断用户是否登录
* @return bool
*/
public function isLogin()
{
$userInfo = cache(config("redis.token_pre") . $this->accessToken);
if (!$userInfo) {
return false;
}
if (!empty($userInfo['id']) && !empty($userInfo['username'])) {
$this->username = $userInfo['username'];
$this->userId = $userInfo['id'];
return true;
}
return false;
}
}
~~~
第二种方法使用中间件 进行检测
在api 文件下 创建一个
![](https://img.kancloud.cn/6e/c6/6ec69c3a1f816ea28fc424a2b0231d22_523x570.png)
修改 middlevare.php 中 对应信息
~~~
<?php
declare (strict_types=1);
namespace app\api\middleware;
class Auth
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
//前置中间件
// if (empty(session('adminUser')) && !preg_match("/login/", $request->pathinfo())) {
// return redirect((string)url('login/index'));
// }
//ajax 返回api格式 例如处理rbac
//这样会处理所有api下的控制器 所以需要
// return $this->show(config("status.not_login"), "没有登录");
if (in_array($request->pathinfo(), config('login.need_verify_login')))
if (!$this->isLogin()) return ajaxReturn(0, '', '未登录,请先登录');
return $next($request);
}
public function end(\think\Response $response)
{
}
/**
* 判断用户是否登录
* @return bool
*/
public function isLogin()
{
$token = request()->header("access-token");
$userInfo = cache(config("redis.token_pre") . $token);
if (!$userInfo) {
return false;
}
if (!empty($userInfo['id']) && !empty($userInfo['username'])) {
return true;
}
return false;
}
}
~~~
## 免登录
打开登录界面 前 执行控制器 的 中间件 进行 验证 获得返回数据 进行 重定向至跳转首页 or 等待用户登录
##退出登录
清空当前redis中 k 拼接 对应的token v 为 null
![](https://img.kancloud.cn/aa/f1/aaf15929fd635a738c52016a46b4775a_1174x404.png)
## model 层代码优化
business 逻辑层 !
![](https://img.kancloud.cn/33/f7/33f78f9c524360383688d951b6f02653_1003x630.png)
model 层![](https://img.kancloud.cn/ff/83/ff835a3a3e362e06d4d55abcc9fe7252_1150x518.png)
这里可以父类继承 调用 减少代码量
![](https://img.kancloud.cn/c1/18/c118236b54088a2b283e75731b41a5f1_1851x1080.png)
## 面向过程 => 面向对象 统一返回给前端
![](https://img.kancloud.cn/be/e5/bee571a2d1d8217d2a80380ff7dbd85a_1920x1051.png)
## 模型 使用
![](https://img.kancloud.cn/35/4c/354cc5e31561dd186d7eb954c9fb0475_1138x356.png)
with 会 `两次`执行sql语句 进行查询 数据量大 大公司常用
withjoin 一次join 查询
## sku 建议用2 方便 直接对应sku表的id
统一规格也使用 sku
![](https://img.kancloud.cn/8b/3b/8b3b440c434659ec6475445c5a28ab72_1066x479.png)
## 系统浏览量 pv
每个商品的浏览量
![](https://img.kancloud.cn/a7/72/a77279101a4a8859f69b7a0e4582b564_866x202.png)
## 商品展示流程
展示商品有自己默认skuid
![](https://img.kancloud.cn/94/08/9408a809ad89a3107b74b4db17436767_893x633.png)
用户点击根据skuid 到sku查询到 该商品的goodsid
然后根据goodsid 到goods 获取该商品信息 和 该商品对应的 所有 sku信息
![](https://img.kancloud.cn/5b/97/5b979c0639c18009b53904d2a5157be0_736x412.png)
![](https://img.kancloud.cn/82/58/82585a710f1162734df4ee6aaf67a804_721x277.png)
这里gids
1,11 :1 : 1 //skuid
1, 11 规格id // 颜色, 尺码
![](https://img.kancloud.cn/1f/e2/1fe2ea2668cdea95d3d3a82d7aa58f26_355x174.png)
![](https://img.kancloud.cn/3a/00/3a00791acdb9c137357ee2db1f1b18ec_268x371.png)
![](https://img.kancloud.cn/b0/c8/b0c8cd1c9c7671fff4c936a51fceb1b7_1177x665.png)
sku
![](https://img.kancloud.cn/23/6e/236e291e7ecfad891de0a843a8d3054b_347x561.png)
## 购物车
浏览器缓存
mysql redis
存redis 高性能
hash
表如何设计的
流程
1.加入购物车
用户登录状态 点击商品加入购物车
即加入redis 中
(1) 到mysql根据skuid查找该商品的sku数据
2.购物车展示页面
3.购物车删除 修改数量
4.购物车排序
![](https://img.kancloud.cn/4b/0d/4b0d6d28010f5914872adc025cf27d37_1920x1051.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020062411424451.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2t4dWthaQ==,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200624114310976.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2t4dWthaQ==,size_16,color_FFFFFF,t_70)
封装在基础类库
hgetall
![](https://img.kancloud.cn/97/55/97551e20b850e54f0e8b470fa53214cb_1037x709.png)
删除 hdel test 1 2
![](https://img.kancloud.cn/17/e5/17e5243b70884df6b208f8ff249f29ac_842x471.png)
获取redis 购物车数据 进行排序
![](https://img.kancloud.cn/3f/f3/3ff363dc9a276dff49e83d59678527dc_795x217.png)
hLen 获取数据
返回值
integer-reply: 哈希集中字段的数量,当 key 指定的哈希集不存在时返回 0
例子
redis> HSET myhash field1 “Hello”
(integer) 1
redis> HSET myhash field2 “World”
(integer) 1
redis> HLEN myhash
(integer) 2
redis>
## 库存 严谨判断 购物车+ 订单 未支付 …2
hMget 返回 key 指定的哈希集中指定字段的值。 对于哈希集中不存在的每个字段,返回 nil 值。
hGetAll 返回 key 指定的哈希集中所有的字段和值。
![](https://img.kancloud.cn/a3/b7/a3b7792b6171c85788c6b2c3bf48e2d3_1071x519.png)
![](https://img.kancloud.cn/17/00/17005dbfaf8e1f54de8de31de9bbf38d_1371x485.png)
订单
主表副表!![](https://img.kancloud.cn/e6/e8/e6e878f30421a1b7f43865cb270c51ef_1422x535.png)
![](https://img.kancloud.cn/91/6a/916afebb43cc0478c1d8bea810cab10e_1138x298.png)
## 订单流程
进入 加入 购物车页面 订单确认页面 和 提交订单页面 都需要判断 `库存`
提交订单流程
1. 删除购物车 的该商品
2. 减库存
3. insert order 主表 副表
## redis 延迟队列处理无效订单
用户点击 确定订单时 未支付
存 redis 20分钟有效期 然后脚本每秒 和当前时间比较 小于当前时间的则 把该订单状态改为 已取消 恢复该订单对应sku的库存
存redis 订单id time()+20min
![](https://img.kancloud.cn/11/60/1160f71b074baff581fb47bbedd2519b_930x491.png)
## 定时任务
![](https://img.kancloud.cn/93/0b/930bd8479b6e77efecc6a253586ba301_945x700.png)
![](https://img.kancloud.cn/51/42/514256597f3978a22c8c82ecef2511cc_915x540.png)
![](https://img.kancloud.cn/93/fd/93fd21cdafba5d5d997f599f3b4dab79_1095x782.png)
暂时有bug 生成 所以要手动挡
![](https://img.kancloud.cn/64/df/64dfc9dc4d62f6742094a9429e37d836_495x798.png)
最后在当前tp6 目录的 命令行 运行 php think order 即可开启进程
如果定时任务 进程挂了这么解决? supervise维持进程任务自动重启
## 支付抽离 单独服务 子服务 微服务
## 写出用户所有流程
支付流程
从购物车点击进入结算 下单页 先减库存
点击立即付款 跳转支付界面 然后看支付回调
成功 失败 进行数据库处理 库存等等…
## Start
前置中间件 检测 是否登录 || 创建一个base来继承 在其中判断 pathinfo 对比
判断前端传来的token 是否存在redis
登录 注册 用redis存储60s 验证码 进行判断 sms . 133333333 验证码 | sms 是标识 拼接手机号 作 k v是验证码 参3存活时间
登录成功 redis 存储 k => user\_token . 后台生成唯一token v => 登录的用户信息 然后把token 给header头
进首页 验证
注册登录
1. 登录流程
验证登录
购物车
订单
支付
- thinkphp6执行流程(一)
- php中use关键字用法详解
- Thinkphp6使用腾讯云发送短信步骤
- 路由配置
- Thinkphp6,static静态资源访问路径问题
- ThinkPHP6.0+ 使用Redis 原始用法
- smarty在thinkphp6.0中的最佳实践
- Thinkphp6.0 搜索器使用方法
- 从已有安装包(vendor)恢复 composer.json
- tp6with的用法,表间关联查询
- thinkphp6.x多对多如何添加中间表限制条件
- thinkphp6 安装JWT
- 缓存类型
- 请求信息和HTTP头信息
- 模型事件用法
- 助手函数汇总
- tp6集成Alipay 手机和电脑端支付的方法
- thinkphp6使用jwt
- 6.0session cookie cache
- tp6笔记
- TP6(thinkphp6)队列与延时队列
- thinkphp6 command(自定义指令)
- command(自定义指令)
- 本地文件上传
- 缓存
- 响应
- 公共函数配置
- 七牛云+文件上传
- thinkphp6:访问多个redis数据源(thinkphp6.0.5 / php 7.4.9)
- 富文本编辑器wangEditor3
- IP黑名单
- 增删改查 +文件上传
- workerman 定时器操作控制器的方法
- 上传文件到阿里云oss
- 短信或者邮箱验证码防刷代码
- thinkphp6:访问redis6(thinkphp 6.0.9/php 8.0.14)
- 实现关联多个id以逗号分开查询数据
- thinkphp6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 用mpdf生成pdf文件(php 8.1.1 / thinkphp v6.0.10LTS )
- 生成带logo的二维码(php 8.1.1 / thinkphp v6.0.10LTS )
- mysql数据库使用事务(php 8.1.1 / thinkphp v6.0.10LTS)
- 一,创建过滤IP的中间件
- 源码解析请求流程
- 验证码生成
- 权限管理
- 自定义异常类
- 事件监听event-listene
- 安装与使用think-addons
- 事件与多应用
- Workerman 基本使用
- 查询用户列表按拼音字母排序
- 扩展包合集
- 查询用户数据,但是可以通过输入用户昵称来搜索用户同时还要统计用户的文章和粉丝数
- 根据图片的minetype类型获取文件真实拓展名思路
- 到处excel
- 用imagemagick库生成缩略图
- 生成zip压缩包并下载
- API 多版本控制
- 用redis+lua做限流(php 8.1.1 / thinkphp v6.0.10LTS )
- 【thinkphp6源码分析三】 APP类之父, 容器Container类
- thinkphp6表单重复提交解决办法
- 小程序授权
- 最简单的thinkphp6导出Excel
- 根据访问设备不同访问不同模块
- 服务系统
- 前置/后置中间件
- 给接口api做签名验证(php 8.1.1 / thinkphp v6.0.10LTS )
- 6实现邮箱注册功能的细节和代码(点击链接激活方式)
- 使用前后端分离的验证码(thinkphp 6.0.9/php 8.0.14/vue 3.2.26)
- 前后端分离:用jwt+middleware做用户登录验证(php 8.1.1 / thinkphp v6.0.10LTS )
- vue前后端分离多图上传
- thinkphp 分组、页面跳转与ajax
- thinkphp6 常用方法文档
- 手册里没有的一些用法
- Swagger 3 API 注释
- PHP 秒级定时任务
- thinkphp6集成gatewayWorker(workerman)实现实时监听
- thinkphp6按月新增数据表
- 使用redis 实现消息队列
- api接口 统一结果返回处理类
- 使用swoole+thinkphp6.0+redis 结合开发的登录模块
- 给接口api做签名验证
- ThinkPHP6.0 + UniApp 实现小程序的 微信登录
- ThinkPHP6.0 + Vue + ElementUI + axios 的环境安装到实现 CURD 操作!
- 异常$e
- 参数请求验证自定义和异常错误自定义