中开启 de_bug
database配置数据库 会先使用 .env 中的配置
tp6 中使用
Db:: 需要 use 门面模式 user think\facade/\Db
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/…
创建 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
可以通过命令行指令快速生成中间件
php think make:middleware Check
namespace app\middleware;
class Check
{
public function handle($request, \Closure $next)
{
// 添加中间件执行代码
...
return $next($request);
}
}
在 app/middleware.php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class
app\middleware\Check::class,
];
composer安装
composer require topthink/think-view
密码 123
md5(‘123_md5’) 处理字符串
composer require topthink/think-captcha
$data = [
'username' => $username,
'password' => $password,
'captcha' => $captcha,
];
$validate = new \app\admin\validate\AdminUser();
if(!$validate->check($data)) {
return show(config("status.error"), $validate->getError());
}
/**
* 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;
}
}
return json [1||0 ,msg ,data]
preg_match()
1 正则
2 str 匹配2中有无 1
return 1 0
session('adminUser', $res); session('adminUser', null);
在business 处理业务逻辑 -> 调用 model 的sql执行 在business进行 异常抛出 在c层try catch 补获
model 放在 common 公共文件里
安装 https://blog.csdn.net/kxukai/article/details/106692983
开启日志 runtime 可以查看执行的原生sql语句 进行分析
短信可以使用redis 进行限制 存手机号 + 发信息间隔时间~
案例:2018年年底 央视春晚 百度手机号登录发送验证码分发不同运营商流量, 就是用这个来做的, 并发50万 发送短信验证码。
简单粗暴 实用 最简单的方法往往最有效
$a = rand(0,99);
if($a < 80) {
// 阿里云逻辑
} else {
// 百度云逻辑
}
捕获异常时 注意记录日志 以供分析
tp6 helper 全局搜索自带抛出异常 throw_if 同laravel
手动抛出异常
throw new \think\Exception("不存在该验证码", config('status.code.not_code'));
捕获异常
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("数据库内部异常");
}
前后端分离 所以是 api 接口
if (!$this->request->isPost() || !$this->request->isAjax() )
return show(config("status.error"), "非法请求");
$phoneNumber = input("phone_number",'','trim');
$code = input("code", 0, "intval");
// 用户输入的 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 进行补获 避免数据库抛出暴露信息被用户查看
5. 还是在common/ business 操作
根据用户手机号 查找有该用户登录记录
// 需要去判断表 是否有 用户记录 phone_number
// 生成token
$user = $this->userObj->getUserByPhoneNumber($data['phone_number']);
这里model 层在 common/model datebase 操作公共的 可以共用
然后进行判断 操作用户记录
6. 然后把生成的token作为k 用户的id 和用户名作为 v 存入redis 存活时间 ~
$redisData = [
"id" => $userId,
"username" => $username,
];
$res = cache(config("redis.token_pre") . $token, $redisData, Time::userLoginExpiresTime($data['type']));
7.最后把前端需要的数据返回
第一种方法 需要验证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 文件下 创建一个
修改 middlevare.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
business 逻辑层
model 层
这里可以父类继承 调用 减少代码量
with 会 两次
执行sql语句 进行查询 数据量大 大公司常用
withjoin 一次join 查询
展示商品有自己默认skuid
用户点击根据skuid 到sku查询到 该商品的goodsid
然后根据goodsid 到goods 获取该商品信息 和 该商品对应的 所有 sku信息
这里gids
1,11 :1 : 1 //skuid
1, 11 规格id // 颜色, 尺码
浏览器缓存
mysql redis
存redis 高性能
hash
表如何设计的
流程
1.加入购物车
用户登录状态 点击商品加入购物车
即加入redis 中
(1) 到mysql根据skuid查找该商品的sku数据
2.购物车展示页面
3.购物车删除 修改数量
4.购物车排序
封装在基础类库
hgetall
删除 hdel test 1 2
获取redis 购物车数据 进行排序
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>
hMget 返回 key 指定的哈希集中指定字段的值。 对于哈希集中不存在的每个字段,返回 nil 值。
hGetAll 返回 key 指定的哈希集中所有的字段和值。
进入 加入 购物车页面 订单确认页面 和 提交订单页面 都需要判断 库存
提交订单流程
用户点击 确定订单时 未支付
存 redis 20分钟有效期 然后脚本每秒 和当前时间比较 小于当前时间的则 把该订单状态改为 已取消 恢复该订单对应sku的库存
存redis 订单id time()+20min
暂时有bug 生成 所以要手动挡
最后在当前tp6 目录的 命令行 运行 php think order 即可开启进程
如果定时任务 进程挂了这么解决? supervise维持进程任务自动重启
支付流程
从购物车点击进入结算 下单页 先减库存
点击立即付款 跳转支付界面 然后看支付回调
成功 失败 进行数据库处理 库存等等…
前置中间件 检测 是否登录 || 创建一个base来继承 在其中判断 pathinfo 对比
判断前端传来的token 是否存在redis
登录 注册 用redis存储60s 验证码 进行判断 sms . 133333333 验证码 | sms 是标识 拼接手机号 作 k v是验证码 参3存活时间
登录成功 redis 存储 k => user_token . 后台生成唯一token v => 登录的用户信息 然后把token 给header头
进首页 验证
注册登录
购物车
订单
支付