TP6简单入门

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的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

彩虹海!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值