# Thinkphp学习笔记
多应用:https://www.kancloud.cn/manual/thinkphp6_0/1297876
composer require topthink/think-multi-app
模板引擎:https://www.kancloud.cn/manual/thinkphp6_0/1037613
composer require topthink/think-view
扩展包推荐
composer require thans/tp-jwt-auth
composer require yunpian/yunpian-php-sdk
composer require overtrue/wechat
phpoffice/phpspreadsheet //excel表单处理
官方文档:https://www.kancloud.cn/manual/thinkphp6_0/1037479
# Http 常用返回状态码
200 : (OK) 服务器已成功处理了请求。 通常,这表示服务器提供了请求的网页。 201 : (Created) 请求成功并且服务器创建了新的资源。 301 : (Moved Permanently) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。 300 : (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。 303 : (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。 304 : (Not Modified) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。 400 : (Bad Request) 服务器不理解请求的语法。 401 : (Unauthorized) 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。 403 : (Forbidden) 服务器拒绝请求。 404 : (Not Found ) 服务器找不到请求的网页。 500 : (Internal Server Error) 服务器遇到错误,无法完成请求。
# 数据返回
laravel, 在thinkphp中吧json
改为 data
/**
* 成功返回消息
* @param string $msg
* @param array $data
* @param int $code
* @return \Illuminate\Http\JsonResponse
*/
public function success($msg="ok",$data=[],$code=0){
if (!empty($data)) return response()->json(["code"=>$code,"data"=>$data,"msg"=>$msg]);
return response()->json(["code"=>$code,"msg"=>$msg]);
}
/**
* 失败返回消息
* @param string $msg
* @param int $code
* @return \Illuminate\Http\JsonResponse
*/
public function error($msg="请求错误",$code=202){
return response()->json(["code"=>$code,"msg"=>$msg]);
}
/**
* 数据返回
* @param array $data
* @param string $count
* @param string $msg
* @param int $code
* @return \Illuminate\Http\JsonResponse
*/
public function resData($data=[],$count = '',$msg="ok",$code=0){
if (empty($count)) return response()->json(["code"=>$code,"msg"=>$msg,"data"=>$data]);
return response()->json(["code"=>$code,"data"=>$data,"count"=>$count,"msg"=>$msg]);
}
# 查询技巧
# join
$data = Score::alias('s')
->join("gift g",'s.sid=g.id')
->field("g.id,g.title,g.pic,s.stime") //需要那个表的字段就假如对应表的字段
->where("uid",$request->uid)
->limit(($page * $limit) - $limit, (int)$limit)
->select()->toArray();
# 别名查询
$data = Articles::where("del",0)
->alias('a')
->join('wy_comment c','a.id=c.aid')
->field("a.id,a.title,,COUNT(c.aid) as comCount")
->limit(($page * $limit) - $limit, (int)$limit)
->order("id","desc")->select()->toArray();
$data = Articles::where("del",0)
->field("id,title,keyword,pic,createtime,click")
->limit(($page * $limit) - $limit, (int)$limit)
->withCount('ArcToCom')
->order("id","desc")->select()->toArray();
//关联查询
->with(['user','parent'])
->visible(['user'=>['realname'],'parent'=>['realname']])
//关联统计
http://localhost:8082/ArticleDetail?eid=26&puid=100
# 关联查询
->with(['user','parent']) //模型关联方法,不是模型的名字
->visible(['user'=>['realname'],'parent'=>['realname']])
# 分页查询
// contoller
public function list(){
$limit = $request->param("limit", 15);
$data = User::order("id","desc")->paginate($limit);
//获取查询数据
$list = $data->items();
// 获取总条数
$count = $data->total();
// json 返回
return json(["code"=>201,"data"=>$list,"count"=>$count]);
}
# 时间段查询
/**
* 时间段查询:2020-10-01 - 2020-11-30
* @param string $datebt
* @return array
*/
protected function getBetweenTime(string $datebt){
$datearr=explode(" - ",$datebt);
$datebegin=strtotime($datearr['0']);
$dateend=strtotime($datearr['1']);
return ['create_time','between',[$datebegin,$dateend]];
}
# A表关联B表,统计B表统计排名
用户可根据分享文章获得的收益sum之后进行排名
UserModel
// 关联浏览记录
public function visit()
{
return $this->hasMany(Visit::class,"muid","id");
}
controller
$top = User::withSum("visit","mprize")->order("visit_sum","desc")->select()->toArray();
# A表关联B表统计B表信息
关联模型
//cate->school
/**
* 分类关联资源
*/
public function school()
{
return $this->hasMany(School::class,'cate_id','id');
}
分类关联资源统计资源的状态为1和2的总数
$data = SchoolCate::withCount([
"school"=>function($query,&$alias){ //这里有一个&符号
$query->where("status",2)->where("check_user_id",session("admin_id"));
$alias='valid';
}
],false)
->withCount([
"school"=>function($query,&$alias){
$query->where("status",4)->where("check_user_id",session("admin_id"));
$alias='unvalid';
}
],false)->where("id","in",$school->getMySchoolIds())->select();
# 获取器
获取器的作用是在获取数据的字段值后自动进行处理,例如,我们需要对状态值进行转换,1 代表:正常
在model下定义: 语法:get + 字段名+Attr
class User extends Model
{
public function getStatusAttr($value)
{
$status = [-1=>'删除',0=>'禁用',1=>'正常',2=>'待审核'];
return $status[$value];
}
}
// 查询输出
$user = User::find()->status; //例如输出“正常”
class User extends Model
{
public function getStatusAttr($value)
{
$status = [-1=>'删除',0=>'禁用',1=>'正常',2=>'待审核'];
return ['val'=>$value,'text'=>$status[$value]];
}
}
$user = User::find()->status; //例如输出“正常”
$user = User::find()->status.text; //例如输出“1”
$user = User::find();
$user->getData("status"); //例如输出“1”
# 远程一对一查询
/**
* 【座位表】通过【班级表】去查【教室】
* 座位关联班级,班级关联教室: 通过【座位】关联【班级】去查【教室】
* 参数:教室模型(目标表),班级模型(中间表),座位表id(目标表),班级表id(中间表),座位表关联班级的关联id(起始表),班级表关联教室的id(中间表)
*/
public function room()
{
return $this->hasOneThrough(Room::class,RoomBj::class,"id","id","bj_id","room_id");
}
# 多字段统计
//model
public function status2()
{
return $this->hasMany(Student::class,"cate_id","id");
}
public function status4()
{
return $this->hasMany(Student::class,"cate_id","id");
}
// controller
public function info()
{
$data = SchoolCate::field("id,cate")
->withCount([
"status2" => function($query){
$query->where('status',2);
},
"status4" => function($query){
$query->where('status',4);
}
])->select()->toArray();
return view("",["data"=>$data]);
}
# 插入并返回插入id
$resId = Mode::insertGetId();
# 去重查询并统计人数
Gw::where("gwssd",$defaultGwssd)
->field("id,zldw,SUM(zlrs) as zlrs")
->group("zldw")
->withCount("zw") //关联方法
->select()->toArray();
# 时间转化
$data['bmstime'] = strtotime($data['bmstime']);
date('Y-m-d H:i:s',$data['bmstime']);
# 多字段统计
->fieldRaw('Sum(prize_value) as totle,SUM(unum) as unum')
# 二维数组排序
$dataKey = array_column($data,"team_count");
array_multisort($dataKey,SORT_DESC,$data);
array_multisort(array_column($Account,'px'),SORT_ASC,$Account);
# ip地址
$request->server("REMOTE_ADDR")
# fieldRaw多字段统计
->fieldRaw('Sum(prize_value) as totle,SUM(unum) as unum')
# 二维数组排序
$dataKey = array_column($data,"team_count");
array_multisort($dataKey,SORT_DESC,$data);
array_multisort(array_column($Account,'px'),SORT_ASC,$Account);
# 验证器使用
/**
* 验证数据正确
* @param array $data
* @param string $scene
* @param bool $batch
* @return array|bool
*/
private function checkNull($data=[],$scene='',$batch=false)
{
$code = 2;
$msg = '';
try {
validate(VoteValidate::class)
->batch($batch)
->scene($scene)
->check($data);
$code = 1;
}catch (ValidateException $e){
$msg = $e->getMessage();
}
if ($code == 1) return true;
return ["code"=>$code,"msg"=>$msg];
}
# 搜索
$limit = $request->param("limit",15);
$search = $request->param('search_word');
$where = [];
$where['vid']=$request->param("vid");
if (!empty($search)) $where['fullname']=['like',"%$search%"];
$data = VoteBm::where($where)->order("id","desc")->paginate();
return json(["code"=>201,"data"=>$data->items(),"count"=>$data->$data->total()]);
User::whereLike("nickname", $keywords.'%')->column("id")
# Php处理Excel
https://phpspreadsheet.readthedocs.io/en/latest/#getting-started
public function importDo(Request $request)
{
$excelFile = $request->file("file");
$check = new ValidateCheck();
$checkRes = $check->checkNull(["uploadExcel"=>$excelFile],'excel');
if ($checkRes !== true) return json($checkRes);
$year = $request->param("year");
$objRead = IOFactory::createReader('Xlsx');
if (!$objRead->canRead($excelFile)) {
$objRead = IOFactory::createReader('Xls');
if (!$objRead->canRead($excelFile)) {
return resMsg(0, '只支持导入Excel文件!', 'reserve' );
}
}
$objPHPExcel = $objRead->load($excelFile); //$file可以是上传的表格,或者是指定的表格
$sheet = $objPHPExcel->getSheet(0); //excel中的第一张sheet
$highestRow = $sheet->getHighestRow(); // 取得总行数
$i = 0; //无效数据
$k=0; //有效数据
$rem='';
for ($j = 2; $j <= $highestRow; $j++) { //从第几行开始导入
$data[$k] = [
'id' => $objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue(),
'name' => $objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue(),
'content' => $objPHPExcel->getActiveSheet()->getCell("C" . $j)->getFormattedValue(),
'year' => $year,
'create_time' => time(),
];
$k++;
}
//排除空值
foreach ($data as $j => $v){
if ($v['code'] == null){
unset($data[$j]);
$i +=1;
}
}
try {
Bm::insertAll($data);
}catch (\ErrorException $e){
return resMsg(2, $e->getMessage(),'index' );
}
if($i !== 0){
return resMsg(1, '导入成功!总计导入'.$k.'条数据!,本次Excel存在无效数据'.$i.'条,岗位代码为空!','index' );
}else {
return resMsg(1, '导入成功!本次导入数据总计'.$k.'条','index' );
}
}
# 一次性插入大量数据处理
$count = ceil(count($data)/500);
for ($h=1;$h<$count+1;$h++){
$offset=($h-1)* 500;
$ids=array_slice($data,$offset,500);
Gw::insertAll($ids);
}
简单粗暴方法
// $list 是一个1W 条二维数组数据,每次插入 1000条
Model::limit(1000)->insertAll($list);
# 动态查询
// 根据邮箱(email)查询用户信息
User::whereEmail('thinkphp@qq.com')
->find();
// 根据昵称(nick_name)查询用户
User::whereNickName('like', '%流年%')
->select();
// 根据邮箱查询用户信息
User::getByEmail('thinkphp@qq.com');
// 根据昵称(nick_name)查询用户信息
User::getByNickName('流年');
// 根据邮箱查询用户的昵称
User::getFieldByEmail('thinkphp@qq.com', 'nick_name');
// 根据昵称(nick_name)查询用户邮箱
User::getFieldByNickName('流年', 'email');
# 字段比较
可以直接比较两个字段的大小进行查询
User::whereColumn('update_time', '>', 'create_time')
->select();
User::whereColumn('score1', '>', 'score2')
->select();
如果需要比较两个字段相同,可以使用
User::whereColumn('score1', 'score2')
->select();
# 时间表达式查询
对于一些非具体的时间查询,比较适合使用时间表达式进行查询,例如:
// 获取今天的博客
Blog::whereTime('create_time', 'today')
->select();
// 获取昨天的博客
Blog::whereTime('create_time', 'yesterday')
->select();
// 获取本周的博客
Blog::whereTime('create_time', 'week')
->select();
// 获取上周的博客
Blog::whereTime('create_time', 'last week')
->select();
// 获取本月的博客
Blog::whereTime('create_time', 'month')
->select();
// 获取上月的博客
Blog::whereTime('create_time', 'last month')
->select();
// 获取今年的博客
Blog::whereTime('create_time', 'year')
->select();
// 获取去年的博客
Blog::whereTime('create_time', 'last year')
->select();
# 关联删除
/**
* 删除
*/
public function delete(Request $request)
{
$id = $request->param("id/d");
$delData = Dks::with(["dkUser","theme","bm","prize","prize"])->find($id);
try {
$delData->together(["dkUser","theme","bm","prize"])->delete();
}catch (\ErrorException $e){
return error($e->getMessage());
}
return success("删除成功!");
}
public function batchDel(Request $request)
{
$ids = $request->param("ids"); //[1,2,3]
try {
foreach ($ids as $item){
Dks::with(["dkUser","theme","bm","prize","prize"])->find($item)->together(["dkUser","theme","bm","prize","prize"])->delete();
}
}catch (\ErrorException $e){
return error($e->getMessage());
}
return success("删除成功!");
}
# 排名统计
假设一个用户去玩一款游戏,每次结束后会产生一个分数,那么一个用户就有多条记录分值的记录,如何在同一张表中统计 每个玩家最高分在总玩家的排名
条件:一张用户表(user),一个记录玩家成绩的记录表(score)(一个玩家有多条记录,我们要取最高分进行排名)
1、去重查询所有用户的id (score)
$allUserIds = Score::distinct(true)->field("uid")->column("uid");
2、通过关联统计的方式查询所有用户的最高分
$data = User::whereIn("id",$allUserIds)->field("id")->withMax("boy","score")->field("id")->select()->toArray(); // boy为关联方法,score为score表的分数字段
// user模型关联方法
public function boy()
{
return $this->hasMany(Score::class,"uid","id");//用 用户表的id,关联积分表的uid
}
3、使用一个foreach
循环
$myTop = 0;
foreach ($data as $item){
if ($item['boy_max'] > $score){
$myTop +=1;
}
}
echo $myTop = $myTop+1;
# JWT-AUTH使用方发
https://gitee.com/thans/jwt-auth
中间件形式:
// app/config/middleware
'alias' => [
"Auth" => thans\jwt\middleware\JWTAuth::class,
],
// controller
protected $middleware = ['Auth'];
$user = [
"name" => "orangbus"
];
// thans/tp-jwt-auth/src/claim/Expiration 15行修改
return ["code" => 1,"msg" => "token已失效!"];
获取toke
$token = JWTAuth::builder($user); echo $token['name']; // orangbus
验证token
//登录验证 JWTAuth::auth(); // token验证 JWTAuth::validate()
刷新token
JWTAuth::refresh(); //返回 token信息,之前的数据依旧存在
# 神兽保护
/**
* _ooOoo_
* o8888888o
* 88" . "88
* (| -_- |)
* O\ = /O
* ___/`---'\____
* . ' \\| |// `.
* / \\||| : |||// \
* / _||||| -:- |||||- \
* | | \\\ - /// | |
* | \_| ''\---/'' | |
* \ .-\__ `-` ___/-. /
* ___`. .' /--.--\ `. . __
* ."" '< `.___\_<|>_/___.' >'"".
* | | : `- \`.;`\ _ /`;.`/ - ` : | |
* \ \ `-. \_ __\ /__ _/ .-` / /
* ======`-.____`-.___\_____/___.-`____.-'======
* `=---='
* .............................................
* 佛曰:bug泛滥,我已瘫痪!
*/