TP6
说明
主要是对tp6进行一个简单的介绍,一些简单的基础使用,具体使用,需要查看tp6手册:https://doc.thinkphp.cn/v6_1/default.html
目录结构
多应用模式
- 多应用模式部署后,记得删除app目录下的controller目录(系统根据该目录作为判断是否单应用的依据)。
配置目录
- 单应用模式的config目录下的所有配置文件系统都会自动读取,如果存在子目录,你可以通过Config类的load方法手动加载,
// 加载config/extra/config.php 配置文件 读取到extra
\think\facade\Config::load(‘extra/config’, ‘extra’);
- 全局配置:config目录下面的文件就是项目的全局配置文件,对所有应用有效。应用配置:每个应用可以有独立配置文件,相同的配置参数会覆盖全局配置。
环境变量定义
- 可以在应用的根目录下定义一个特殊的.env环境变量文件,用于在开发过程中模拟环境变量配置, .env 配置在Windows和linux系统都适用
- 要使用Env类,必须先引入think\facade\Env,获取环境变量的值,Env::get(‘database.username’);
配置获取
- 要使用Config类,首先需要在你的类文件中引入,use think\facade\Config; $databaseconfig= Config::get(“database.connections.mysql.type”);
架构
多应用模式
- 如果要使用多应用模式,你需要安装多应用模式扩展think-multi-app。 composer require topthink/think-multi-app
URL设计
- http://serverName/index.php(或者其它入口文件)—>web目录下的 /控制器/操作(方法)/参数/值…
- 多应用:web目录下的 /应用名/控制器/操作(方法)/参数/值…
依赖注入
- 对于自定义的类以及方法,如果需要使用依赖注入,需要使用系统提供的invoke助手函数调用 $foo = invoke(‘Foo’);
绑定
- 依赖注入的类统一由容器进行管理,大多数情况下是在自动绑定并且实例化的,不过你可以随时进行手动绑定类到容器中(通常是在服务类的register方法中进行绑定),支持多种绑定方式。
- 绑定类标识:// 绑定类库标识 $this->app->bind(‘think\Cache’, ‘app\common\Cache’); 或者使用助手函数:bind(‘cache’, ‘think\Cache’);
…
中间件
- 请求会经过中间件进行过滤
事件
- 我们通常会遇到用户注册或者登录后需要做一系列操作,通过事件系统可以做到不侵入原有代码完成登录的操作扩展,降低系统的耦合性的同时,也降低了BUG的可能性。
- 事件系统的所有操作都通过think\facade\Event类进行静态调用
定义事件
*事件系统使用了观察者模式,提供了解耦应用的更好方式。在你需要监听事件的位置,例如下面我们在用户完成登录操作之后添加如下事件触发代码:
// 触发UserLogin事件 用于执行用户登录后的一系列操作
Event::trigger(‘UserLogin’);
或助手函数
event(‘UserLogin’);
- 这里UserLogin表示一个事件标识,如果你定义了单独的事件类,你可以使用事件类名(甚至可以传入一个事件类实例)。
// 直接使用事件类触发
event(‘app\event\UserLogin’);
- 还有事件监听,事件订阅
路由
- 要使用Route类注册路由必须首先在路由定义文件开头添加引用use think\facade\Route;,多应用或自己创建的路由要引入,使用Route进行配置
路由定义
- Route::rule(‘路由表达式’, ‘路由地址’, ‘请求类型’);
- Route::get(“/nyd/:year/:mouth/:day”,“/admin/getYMD”); year:对应方法的参数名/nyd/2024/11/22
可选变量
- Route::get(‘blog/:year/[:month]’,‘Blog/archive’); 可选参数只能放到路由规则的最后,如果在中间使用了可选参数的话,后面的变量都会变成可选参数。
完全匹配
- 可以在路由表达式最后使用$符号
- 路由配置文件中设置:
// 开启路由完全匹配
‘route_complete_match’ => true,
- 开启全局完全匹配后,如果需要对某个路由关闭完全匹配,可以使用 Route::get(‘new/:cate’, ‘News/category’)->completeMatch(false);
额外参数
- 在路由跳转的时候支持额外传入参数对
Route::get(“/nyd/:year/:mouth/[:day]”,“/admin/getYMD”)->append([‘extra’=>‘额外参数’]);
public function getYMD( y e a r = 0 , year=0, year=0,mouth=0, d a y = 0 , day=0, day=0,extra){
return e x t r a . " 年 " . extra."年". extra."年".year.“月”. m o u t h . " 日 " . mouth."日". mouth."日".day.“<br>”;
}
路由地址
- Route::get(‘/blog/:id$’,‘/blog.Read/readit’)->pattern([‘id’=>‘\d+’]); 多级控制器
路由到类
- 这种方式的路由可以支持执行任何类的方法,而不局限于执行控制器的操作方法。
\完整类名@方法名 \完整类名::方法名(静态) Route::get(‘/blog’,‘\app\admin\service\Admin@aservice’);
重定向路由
- 可以直接使用redirect方法注册一个重定向路由 Route::redirect(‘/tobaidu’, ‘http://www.baidu.com/’, 200);
路由到模板
路由到闭包
- 我们可以使用闭包的方式定义一些特殊需求的路由,而不需要执行控制器的操作方法了
Route::get(“/hello/<name>”, function ($name) {
echo $name.“<br>”;
response()->data(‘thinkphp’)
->code(200)
->contentType(‘text/plain’);
});
路由参数
- 如果你需要批量设置路由参数,也可以使用option方法
Route::get(‘new/:id’, ‘News/read’)
->option([
‘ext’ => ‘html’,
‘https’ => true
]);
路由检测|闭包检测
Route::get(‘/:id’,‘/admin/hello’)->option([
‘domain’=> ‘tp6.study’,
])->filter([‘status’=>1]);
- 地址:http://tp6.study/admin/1?status=1
- 可以通过闭包来检测当前路由或分组是否匹配
Route::get(‘new/:id’, ‘News/read’)
->match(function(Rule $rule,Request $request) {
// 如果返回false 则视为不匹配
return false;
});
路由中间件
- Route::rule(“/hello/:id”,“/admin/hello”,“get”)->middleware([\app\admin\middleware\Admin::class]);middleware:指定中间件
资源路由
- ->vars([‘blog’ => ‘blog_id’]);通过这个指向方法参数名
- ->only([‘index’, ‘read’, ‘edit’, ‘update’]);允许操作
- ->except([‘index’, ‘delete’]); 排除操作
- ->allowCrossDomain(); 允许所有域名跨域
控制器
基础控制器
- 我们建议给你的控制器继承一个基础控制器。默认安装后,系统提供了一个app\BaseController基础控制器类,你可以对该基础控制器进行修改
- 该基础控制器仅仅提供了控制器验证功能,并注入了think\App和think\Request对象,因此你可以直接在控制器中使用app和request属性调用think\App和think\Request对象实例,
- 空控制器的概念是指当系统找不到指定的控制器名称的时候,系统会尝试定位当前应用下的空控制器(Error)类,利用这个机制我们可以用来定制错误页面和进行URL的优化。
请求
- 当前的请求对象由think\Request类负责,该类不需要单独实例化调用,通常使用依赖注入即可。在其它场合则可以使用think\facade\Request静态类操作。( Request::param(‘name’))
- 助手函数:系统还提供了request助手函数,可以在任何需要的时候直接调用当前请求对象。return request()->param(‘name’);
变量过滤
-
use think\facade\Request; 以这个为例
-
框架默认没有设置任何全局过滤规则,你可以在app\Request对象中设置filter全局过滤属性:namespace app;
class Request extends \think\Request
{
protected $filter = [‘htmlspecialchars’];
} -
也可以在获取变量的时候添加过滤方法,例如:
Request::get(‘name’,‘’,‘htmlspecialchars’); // 获取get变量 并用htmlspecialchars函数过滤
Request::param(‘username’,‘’,‘strip_tags’); // 获取param变量 并用strip_tags函数过滤
Request::post(‘name’,‘’,‘org\Filter::safeHtml’); // 获取post变量 并用org\Filter类的safeHtml方法过滤
Request::param(‘username’,‘’,‘strip_tags,strtolower’); // 获取param变量 并依次调用strip_tags、strtolower函数过滤
获取部分变量
// 只获取当前请求的id和name变量
Request::only([‘id’,‘name’]);
- 采用only方法能够安全的获取你需要的变量,避免额外变量影响数据处理和写入。
// 只获取POST请求的id和name变量
Request::only([‘id’=>0(默认值),‘name’], ‘post’);
// 等效于
Request::post([‘id’, ‘name’]);
变量修饰符
- 支持对变量使用修饰符功能,可以一定程度上简单过滤变量 Request::变量类型(‘变量名/修饰符’);
请求类型伪装
- 支持请求类型伪装,可以在POST表单里面提交_method变量,传入需要伪装的请求类型
<form method="post" action="">
<input type="text" name="name" value="Hello">
<input type="hidden" name="_method" value="PUT" >
<input type="submit" value="提交">
</form>
- 提交后的请求类型会被系统识别为PUT请求。
响应
- ThinkPHP的Response响应对象由think\Response类或者子类完成,ThinkPHP的响应输出是自动的(命令行模式除外),最终会调用Response对象的send方法完成输出。
- Response类不能直接实例化,必须使用 Response::make() 静态方式创建,建议直接使用系统提供的助手函数完成。
- 大多数情况,我们不需要关注Response对象本身,只需要在控制器的操作方法中返回数据即可
- return json($data) :json输出,return response($data):html输出
响应参数
- Response对象提供了一系列方法用于设置响应参数,包括设置输出内容、状态码及header信息等,并且支持链式调用以及多次调用。
- Response基类提供了data方法用于设置响应数据
public function index(){
// response(“你好”,200);
return response()->data(“你好”)->code(200)->cookie(“name”,“aa”,600);
}
重定向
- 可以使用redirect助手函数进行重定向
public function toBaidu(){
// return redirect(“http://www.baidu.com”);
return redirect(“/admin/admin”);
}
文件下载
- 助手 download 函数
- 助手函数提供了内容下载的参数,如果需要直接下载内容,可以在第三个参数传入true,就是下载到浏览器
$data = ‘这是一个测试文件’;
return download($data, ‘test.txt’, true);
数据库
数据分批处理
- 如果你需要处理成千上百条数据库记录,可以考虑使用chunk方法,该方法一次获取结果集的一小块,然后填充每一小块数据到要处理的闭包,该方法在编写处理大量数据库记录的时候非常有用。chunk方法一般用于命令行操作批处理数据库的数据,不适合WEB访问处理大量数据,很容易导致超时。
Db::table('user')->where('id','<','114')->chunk(3,function ($users){
foreach($users as $user){
echo $user['id'].'->'.$user['name'].'<br>';
if($user['id']==113){
return false;//终止
}
}
},'id','asc');//根据id升序
echo '<pre>';
- 如果你需要处理大量的数据,可以使用新版提供的游标查询功能,该查询方式利用了PHP的生成器特性,可以大幅减少大量数据查询的内存开销问题
$cursor = Db::table('user')->cursor();
foreach ($cursor as $user) {
echo $user['name'] . '<br>';
}
添加数据
- 添加数据后如果需要返回新增数据的自增主键,可以使用insertGetId方法新增数据并返回主键值: Db::name(‘user’)->insertGetId($data);
模型
- 模型会自动对应数据表,模型类的命名规则是除去表前缀的数据表名称,采用驼峰法命名,并且首字母大写 模型名:UserType->user_type
- 模型属性
严格区分字段大小写
- 默认情况下,你的模型数据名称和数据表字段应该保持严格一致,也就是说区分大小写
- 如果你希望在获取模型数据的时候不区分大小写(前提是数据表的字段命名必须规范,即小写+下划线),可以设置模型的strict属性。protected $strict = false,// 下面两种方式都有效echo $user->createTime; echo $user->create_time;
- 模型数据转驼峰:可以设置convertNameToCamel属性使得模型数据返回驼峰方式命名(前提也是数据表的字段命名必须规范,即小写+下划线)。
$user = new User;
// post数组中只有name和email字段会写入
$user->allowField([‘name’,‘email’])->save($_POST);
新增
- 默认只会写入数据表已有的字段,如果你通过外部提交赋值给模型,并且希望指定某些字段写入
- 静态方法create() 还可以直接静态调用create方法创建并写入:和save方法不同的是,create方法返回的是当前模型的对象实例。create方法默认会过滤不是数据表的字段信息,可以在第二个参数可以传入允许写入的字段列表
public function insert(){
$user = User::create(
['name'=>'aaa']
,['name']);
}
视图
- 通常可以直接使用think\facade\View来操作视图。 安装 驱动:composer require topthink/think-view
模板渲染
- 默认情况下,框架会自动定位你的模板文件路径,优先定位应用目录下的view目录,这种方式的视图目录下就是应用的控制器目录。
- controller目录下的类对应模板view下面的一个文件夹,controller操作对应模板文件,如index.html…
- 渲染内容:如果希望直接解析内容而不通过模板文件的话,可以使用display方法
// 直接渲染内容
$content = ‘<h1>{$name}</h1>’;
return View::display($content,[‘name’=>‘你好’]);
- 他会替换html的全部内容
- 调用其他项目的模板
public function index(){
//项目testproject下的view/member文件夹/a.html
// return View::fetch(‘testproject@member/a’);
return View::fetch(‘bb/b’);//调用本项目下的view/bb/b.html
}
模板变量
- 模板就是渲染到前端的一套规则
- 可以使用assign方法进行全局模板变量赋值。
public function getParam(){
View::assign(“title”,“我是标题”);
return View::fetch();
}
视图过滤
public function index()
{
// 使用视图输出过滤
return View::filter(function($content){
return str_replace("\r\n",'<br/>',$content);
})->fetch();
}
- 助手函数
public function index()
{
// 使用视图输出过滤
return view()->filter(function($content){
return str_replace("\r\n",'<br/>',$content);
});
}
模板标签
普通模板
- 针对变量做简单的运算,函数操作
- 可以直接在模板中使用的系统变量$_SERVER,$_ENV,$_POST,$_GET,$_SESSION,$COOKIE
函数
- default:默认值 md5:md5加密,date:日期格式化,format:字符串格式化,%d upper:转换大写,lower:转换小写,
- first,last:分别输出数组第一个和最后一个元素,substr:返回字符串的一部分
$users = Db::table('user')->whereIn('id',[1,111])->select();
View::assign('users',$users);
echo "<pre>";
print_r($users);
return View::fetch();
<h1>我是模板文件的首页</h1>
<div>{$name|default='张三'}</div>
<div>{$users[0]['name']|md5}</div>
<div>{$users[0]['create_date']|date='Y-m-d H:i:s'}</div>
<div>{$users[0]['name']|upper}</div>
<!-- 不会被解析 -->
<div>
{literal}
hello,{$users[0]['name']}
{/literal}
</div>
XML模板
- 主要是对标签做一些逻辑判断,循环等
- 包含文件 {include file=“public/header” /} view/public/header.html
循环标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{include file="public/header" /}
{foreach $users as $key => $value}
<div>姓名:{$value['name']}</div>
{/foreach}
{for start='10' end='30' name='a' step='5'}
<div>{$a}</div>
{/for}
{switch $users[0]['name']}
{case 魔法天女}
<div>我是魔法天女</div>
{/case}
{default /}
<div>啥也不是</div>
{/switch}
{if $users[0]['name']=='魔法天女'}
<div>优秀</div>
{elseif $users[0]['name']=='李小龙' /}
<div>无敌</div>
{else /}
<div>啥也不是</div>
{/if}
</body>
</html>
异常处理
- 框架支持异常处理由开发者自定义类进行接管,需要在app目录下面的provider.php文件中绑定异常处理类
- 系统提供了助手函数abort简化HTTP异常的处理
// 抛出404异常
abort(404, ‘页面异常’);
验证器
- ThinkPHP推荐使用验证器,可以在控制器中使用validate助手函数(或者封装验证方法)进行验证。
验证器定义
- 具体的验证场景或者数据表定义好验证器类,直接调用验证类的check方法即可完成验证
app\validate\User.php
<?php
namespace app\validate;
use think\Validate;
class User extends Validate{
protected $rule = [
'name' => 'require|max:5',
'age' => 'number|between:1,120',
'email' => 'email',
];
protected $message = [
'name.require' => '名称必须',
'name.max' => '名称最多不能超过25个字符',
'age.number' => '年龄必须是数字',
'age.between' => '年龄只能在1-120之间',
'email' => '邮箱格式错误',
];
}
app\controller\Index.php
<?php
namespace app\controller;
use app\BaseController;
use app\validate\User as UserValidate;//引入验证器
use think\exception\ValidateException;
class Index extends BaseController
{
public function hello()
{
try {
validate(UserValidate::class)->check([
'name' => 'thinkphp',
'email' => 'thinkphp@qq.com',
]);
} catch (ValidateException $e) {
// 验证失败 输出错误信息
dump($e->getError());
}
}
}
路由验证
软删除
- 软删除的字段,删除之后会保存删除的时间戳
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model{
use SoftDelete;
protected $deleteTime = "delete_time";//删除标识
protected $defaultSoftDelete = 0;//删除标识的默认值
public function index(){
return User::destroy(116);//使用destroy删除
}
}
项目搭建
下载tp6,下载多应用插件,去官网看
新建项目目录
-
在app下新建admin应用,admin/controller|route
route/admin.php 路由配置
<?php use think\facade\Route; Route::get("demo","demo/index"); ?>
controller/Demo.php 控制器
<?php namespace app\admin\controller; class Demo{ public function index(){ return "demo index"; } } ?>
小皮环境
跟目录选择public目录,此时访问tp6.lesson/admin/demo 报404,说明没设置伪静态
在public下的.htaccess设置伪静态
.htaccess文件
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>
验证器
admin/validate/Account.php 新建
<?php
namespace app\admin\validate;
use think\Validate;
class Account extends Validate
{
//验证规则
protected $rule = [
"username" => "require",
"password" => "require",
];
//验证信息
protected $message = [
"username.require" => "账号不能为空",
"password.require" => "密码不能为空"
];
//验证场景,login需要验证
protected $scene = [
"login" => ["username", "password"],
];
}
?>
编写中间件
基础知识
- 在Web开发中,中间件是指对HTTP请求和响应进行处理的一种方式。当客户端发送请求至服务器时,HTTP请求会经过多个中间件,最后返回响应给客户端。
中间件
新建admin/middleware/Account.php
<?php
namespace app\admin\middleware;
//引用验证器
use app\admin\validate\Account as AccountValidate;
use think\exception\ValidateException;
class Account{
public function handle($request, \Closure $next){
//获取参数
$params = $request->param();
//验证参数
try{
validate(AccountValidate::class)->scene("login")->check($params);
}catch(ValidateException $e){
return json(['msg'=>$e->getMessage()],201);
// throw new \Exception("参数异常");
}
return $next($request);
}
}
?>
在路由中添加中间件Route::post(“account/login”,“account/login”)->middleware(app\admin\middleware\Account::class);
访问:postman 访问 http://tp6.lesson/admin/account/login 参数正常才会通过
模型
基模型 admin/model/BaseModel.php
<?php
namespace app\admin\model;
use think\Model;
class BaseModel extends Model
{
}
?>
新建admin/model/Account.php
<?php
<?php
namespace app\admin\model;
class Account extends BaseModel{
//数据库的表
protected $tablename = "account";
//验证用户名和密码
public function check ($username,$pasword){
return self::where("username",$username)->where("password",$pasword)->find();
}
}
?>
中间件新增验证
<?php
namespace app\admin\middleware;
//引用验证器
use app\admin\validate\Account as AccountValidate;
use think\exception\ValidateException;
use app\admin\model\Account as AccountModel;
class Account{
public function handle($request, \Closure $next){
//获取参数
$params = $request->param();
//验证参数
try{
validate(AccountValidate::class)->scene("login")->check($params);
}catch(ValidateException $e){
return json(['msg'=>$e->getMessage()],201);
// throw new \Exception("参数异常");
}
$exist= (new AccountModel())->check($params['username'], $params['password']);
if(!$exist){
return json(['msg'=>'账户不存在']);
}
//将查出来的数据封装的request中,方便控制器获取
$params['id']=$exist['id'];
$params['scope']=$exist['scope'];
$request->params = $params;
return $next($request);
}
}
?>
自定义返回
<?php
namespace app\admin\common;
class Result {
//success
static public function Success($data) {
$rs = [
'code'=>0,
'msg'=>"success",
'data'=>$data,
];
return json($rs);
}
//error
static public function Error($code,$msg) {
$rs = [
'code'=>$code,
'msg'=>$msg,
'data'=>"",
];
return json($rs);
}
}
登录接口
<?php
namespace app\admin\controller;
use app\admin\common\Result;
use app\Request;
class Account{
public function login(Request $request){
$params = $request->params;
return Result::Success($params);
}
}
?>
Day1
开启redis缓存
- 进入config/cache.php
<?php
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 默认缓存驱动.切换为redis驱动
'default' => env('cache.driver', 'redis'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 更多的缓存连接
'redis' => [
'host' => '127.0.0.1',
'port' => 6379,
'password' => '123456',
'select' => 1,
// 'timeout' => 0,
// 'expire' => 0,
// 'persistent' => false,
// 'prefix' => '',
// 'tag_prefix' => 'tag:',
// 'serialize' => [],
]
],
];
开启redis扩展
- 在php.ini加上:extension=php_redis.dll extension=gettext
公共返回类
admin/common/Result.php
<?php
namespace app\admin\common;
class Result {
//success
static public function Success($data) {
$rs = [
'code'=>0,
'msg'=>"success",
'data'=>$data,
];
return json($rs);
}
//error
static public function Error($code,$msg) {
$rs = [
'code'=>$code,
'msg'=>$msg,
'data'=>"",
];
return json($rs);
}
}
创建service
admin/servie/Account.php
<?php
namespace app\admin\service;
class Account{
public function getToken($params){
$scope = $params['scope'];
$uid = $params['id'];
$values=[
'scope'=> $scope,
'uid'=> $uid
];
$token = $this->saveToCache($values);
return $token;
}
private function saveToCache($values){
$token = $this->generateToken();//生成token
$expire = config('secure.token_expire');//获取token过期时间
$result = cache($token,json_encode($values),$expire);//redis缓存数据
if(!$result){
throw new \Exception('服务器缓存异常');
}
return $token;
}
public static function generateToken(){
//生成随机字符串
$randChar= getRandChar(32);
$timestamp = $_SERVER['REQUEST_TIME_FLOAT'];//获取请求开始的时间戳
$tokenSalt = config('secure.token-salt');//config目录下的secure变量
$token = md5($randChar . $timestamp .$tokenSalt);//md5加密
return $token;
}
}
?>
公共应用文件
- 公共应用文件不需要引入
app/common.php
<?php
// 应用公共文件
//生成$length位的随机字符串
function getRandChar($length){
$str = null;
$strpool = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$strlen = strlen($strpool)-1;
for($i = 0; $i < $length; $i++){
$str .= $strpool[rand(0,$strlen)];
}
return $str;
}
config文件
admin/config/secure.php 可以直接config(‘secure.变量’)来使用里面的变量
<?php
return [
"token-salt"=> "ABC",
"token_expire"=>7200,
];
登录controller
- 以后不重复复制了,会在这些基础上扩展代码,看不懂的可以看文档后面
<?php
namespace app\admin\controller;
use app\admin\common\Result;
use app\Request;
use app\admin\service\Account as AccountService;
class Account
{
/**
* 登录:当请求登录接口的时候,中间件先过滤,将参数信息保存到request中
* 生成token,保存token,返回token
*/
public function login(Request $request)
{
$params = $request->params;
$token = (new AccountService())->getToken($params);
return Result::Success($token);
}
/**
* 获取uid:
* 每次请求都会经过中间件,验证token是否合法,合法将uid保存到request域中
* 返回uid
*/
public function info(Request $request)
{
$uid = $request->uid;
return Result::Success(["uid"=>$uid]);
}
}
?>
令牌校验
中间件过滤
middleware/Auth.php
<?php
namespace app\admin\middleware;
use app\admin\service\Token;
class Auth
{
//token校验
public function handle($request, \Closure $next)
{
$token = $request->header("token");
if (empty($token)) {
throw new \Exception("token不存在");
}
//检查token并获取uid
$uid = Token::checkPrimaryScope($token);
//保存uid到request域中
$request->uid = $uid;
return $next($request);
}
}
?>
token 验证service
<?php declare(strict_types=1);
namespace app\admin\service;
class Token
{
private static $token = '';
public static function checkPrimaryScope(string $token): int
{
self::$token = $token;
$scope = self::getCurrentTokenVar('scope');
if ($scope >= 32) {
//说明权限是够的,返回id
return self::getCurrentTokenVar('uid');
} else {
throw new \Exception('权限不够');
}
}
public static function getCurrentTokenVar(string $key)
{
//从redis取出数据
$var = cache(self::$token);
if (!$var) {
throw new \Exception('token值不存在');
} else {
//如果不是json字符串转换成数组类型
if (!is_array($var)) {
$var = json_decode($var,true);
}
//判断数组的键是否存在【"scope":32,"uid":1】 获取scope权限
if (array_key_exists($key, $var)) {
return $var[$key];
} else {
throw new \Exception('权限查询失败');
}
}
}
}
?>
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了tp6的使用