json() 提供 方法
修改 開啟報錯查看

## env
中開啟 de\_bug
database配置數據庫 會先使用 .env 中的配置!


tp6 中使用
**Db**:: 需要 use 門面模式 user think\\facade/\\Db

## 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


## has 判斷某個值是否設置
## 容器和依賴注入


## 全局中間件
可以通過命令行指令快速生成中間件
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,
];
~~~
## 應用中間件

## 模板引擎
composer安裝

```
composer require topthink/think-view
```
## 簡單的密碼+鹽處理
密碼 123
md5(‘123\_md5’) 處理字符串
## 驗證碼
```
composer require topthink/think-captcha
```


驗證碼使用 驗證是時 徐快需要在中間件中開啟session!

## 模型分層架構

思維
## 驗證器
~~~
$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 注意

## 如何正確分層之操作datebase
## 注意使用 init初始化
## 如何處理在init里無法重定向

## 注意 如何 /admin/index/index 寫的時候需要+ /’
## 前置中間件

preg\_match()
1 正則
2 str 匹配2中有無 1
return 1 0
## 后置中間件

## session
~~~
session('adminUser', $res); session('adminUser', null);
~~~
* 1
## business 業務邏輯層
在business 處理業務邏輯 -> 調用 model 的sql執行 在business進行 異常拋出 在c層try catch 補獲
model 放在 common 公共文件里

## redis 實現驗證碼 存活時間60s
安裝 https://blog.csdn.net/kxukai/article/details/106692983
## 日志
開啟日志 runtime 可以查看執行的原生sql語句 進行分析
](images/screenshot_1653443315790.png)
## 工廠模式



短信可以使用redis 進行限制 存手機號 + 發信息間隔時間~
## 如何流控 20%阿里云短信 80%百度云短信
案例:2018年年底 央視春晚 百度手機號登錄發送驗證碼分發不同運營商流量, 就是用這個來做的, 并發50萬 發送短信驗證碼。
簡單粗暴 實用 最簡單的方法往往最有效
~~~
$a = rand(0,99);
if($a < 80) {
// 阿里云邏輯
} else {
// 百度云邏輯
}
~~~
## 前后端分離 redis+ token 不使用session+cookie
## config(‘statis.success’)

## 異常處理 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("數據庫內部異常");
}
~~~

## 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 進行補獲 避免數據庫拋出暴露信息被用戶查看

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.最后把前端需要的數據返回
## 中間件 進行 前端 檢測是否登錄 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 文件下 創建一個

修改 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

## model 層代碼優化
business 邏輯層?!

model 層
這里可以父類繼承 調用 減少代碼量

## 面向過程 => 面向對象 統一返回給前端

## 模型 使用

with 會?`兩次`執行sql語句 進行查詢 數據量大 大公司常用
withjoin 一次join 查詢
## sku 建議用2 方便 直接對應sku表的id
統一規格也使用 sku

## 系統瀏覽量 pv
每個商品的瀏覽量

## 商品展示流程
展示商品有自己默認skuid

用戶點擊根據skuid 到sku查詢到 該商品的goodsid
然后根據goodsid 到goods 獲取該商品信息 和 該商品對應的 所有 sku信息


這里gids
1,11 :1 : 1 //skuid
1, 11 規格id // 顏色, 尺碼



sku

## 購物車
瀏覽器緩存
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>
## 庫存 嚴謹判斷 購物車+ 訂單 未支付 …2
hMget 返回 key 指定的哈希集中指定字段的值。 對于哈希集中不存在的每個字段,返回 nil 值。
hGetAll 返回 key 指定的哈希集中所有的字段和值。


訂單
主表副表!

## 訂單流程
進入 加入 購物車頁面 訂單確認頁面 和 提交訂單頁面 都需要判斷?`庫存`
提交訂單流程
1. 刪除購物車 的該商品
2. 減庫存
3. insert order 主表 副表
## redis 延遲隊列處理無效訂單
用戶點擊 確定訂單時 未支付
存 redis 20分鐘有效期 然后腳本每秒 和當前時間比較 小于當前時間的則 把該訂單狀態改為 已取消 恢復該訂單對應sku的庫存
存redis 訂單id time()+20min

## 定時任務



暫時有bug 生成 所以要手動擋

最后在當前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
- 參數請求驗證自定義和異常錯誤自定義