学习笔记20251230
JWT的使用
流程图
flowchart TD
A[生成token] --> B(基类服务<br>BaseService->createToken)
B --> C[Jwt工具类<br>JwtAuthUtil->createToken]
D[验证token<br>请求头携带token] --> F[权限中间件<br>AuthMidd->handle]
F --> G[权限服务<br>AuthService->parseToken]
G --> H[Jwt工具类<br>JwtAuthUtil->parseToken<br>JwtAuthUtil->verifyToken]
使用firebase/php-jwt包进行封装
// composer require firebase/php-jwt
<?php
namespace app\utils;
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
class JwtAuth
{
protected $secretKey = 'your-secret-key';
protected $token = null;
/**
* @param $id
* @return string
*/
public function getToken($id): string
{
// 配置信息
$issuedAt = time();
$expirationTime = $issuedAt + 3600; // 1小时过期
$serverName = "yourdomain.com";
// 创建 payload
$payload = [
'iat' => $issuedAt, // 签发时间
'iss' => $serverName, // 签发者
'nbf' => $issuedAt, // 生效时间
'exp' => $expirationTime, // 过期时间
'data' => [ // 自定义数据
'userId' => $id
]
];
// 生成 token
return JWT::encode($payload, $this->secretKey, 'HS256');
}
/**
* 解析token
* @param string $token
* @return array
*/
public function parseToken(string $token = ''): array
{
$this->token = $token;
list($headb64, $bodyb64, $cryptob64) = explode('.', $this->token);
$payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64));
return [$payload->data->userId];
}
/**
* @return void
*/
public function verifyToken()
{
JWT::$leeway = 60;
$decoded = JWT::decode($this->token, new Key($this->secretKey, 'HS256'));
$this->token = null;
}
}
// BaseServices类设计
<?php
namespace app\services;
use app\utils\JwtAuth;
abstract class BaseServices
{
public function createToken(int $id)
{
$jwtAuth = app()->make(JwtAuth::class);
return $jwtAuth->getToken($id);
}
}
// 验证token设计
<?php
namespace app\middleware;
use app\Request;
use app\services\user\AuthService;
use Closure;
class AuthTokenMiddleware
{
/**
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$token = $this->extractToken($request);
/** @var AuthService $authService */
$authService = app()->make(AuthService::class);
$data = $authService->parseToken($token);
$request->macro('userInfo', function () use (&$data) {
return $data;
});
return $next($request);
}
/**
* @param Request $request
* @return string|null
*/
private function extractToken(Request $request): ?string
{
// 从 Authorization 头获取
$header = $request->header('Authorization');
if (preg_match('/Bearer\s+(.*)$/i', $header, $matches)) {
return $matches[1];
}
// 从查询参数获取
return $request->get('token');
}
}
// AuthService
<?php
namespace app\services\user;
use app\dao\user\UserDao;
use app\services\BaseServices;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use app\exception\ApiException;
use app\utils\JwtAuth;
class AuthService extends baseServices
{
/**
* @var UserDao
*/
protected $useDao;
/**
* @param UserDao $userDao
*/
public function __construct(UserDao $userDao)
{
$this->useDao = $userDao;
}
/**
* @param string $token
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function parseToken(string $token = ''): array
{
if (!$token || $token === 'undefined') {
throw new ApiException(10001);
}
/** @var JwtAuth $jwtAuth */
$jwtAuth = app()->make(JwtAuth::class);
//设置解析token
[$id] = $jwtAuth->parseToken($token);
//验证token
try {
$jwtAuth->verifyToken();
} catch (\Throwable $e) {
throw new ApiException([10002, $e->getMessage()]);
}
$userInfo = $this->useDao->getById($id);
return $userInfo->hidden(['pwd'])->toArray();
}
}
Trait的使用
Trait 在PHP中是一种水平代码复用机制,用于解决单继承语言的局限性。简单说,它就像一组可以“复制粘贴”到多个类中的方法集合,让不同继承链的类能共享相同的行为。
核心对比:Trait vs 抽象类 vs 接口
| 特性 | Trait | 抽象类 (Abstract Class) | 接口 (Interface) |
|---|---|---|---|
| 核心目的 | 代码复用 (水平注入) | 定义模板/契约 (垂直继承) | 定义纯契约 (要求实现) |
| 如何关联 | use 关键字 (在类内部) |
extends 关键字 |
implements 关键字 |
| 数量限制 | 一个类可以use多个Trait |
单继承 (只能extends一个) |
多实现 (可implements多个) |
| 包含内容 | 方法、属性(均可包含实现) | 抽象方法、具体方法、属性 | 方法签名、常量(PHP 8.0前) |
| 实例化 | 不能直接实例化 | 不能直接实例化 | 不能直接实例化 |
| 关系比喻 | “技能书”:给英雄装备不同的技能 | “职业蓝图”:规定一个职业必须会什么,并提供部分基础 | “资格证书”:只声明需要考核的技能项,不教你怎么做 |
-
Macroable的使用
spatie/macroable是知名 PHP 开发团队 Spatie 发布的一个轻量级开源库。它的核心功能是通过一个 Trait,让你能在运行时为 PHP 类动态地添加新方法,而无需修改原始类的代码。demo
//composer require spatie/macroable use Spatie\Macroable\Macroable; class MyClass { use Macroable; } // 动态添加一个方法 MyClass::macro('sayHello', function (string $name): string { return "Hello, {$name}!"; }); $instance = new MyClass(); echo $instance->sayHello('World'); // 输出:Hello, World!Macroable使用场景
-
在Request对象添加额外数据
比如
namespace app; // 应用请求对象类 use Spatie\Macroable\Macroable; class Request extends \think\Request { // 使用MacroableTrait use Macroable; } // 应用 $data = user::get(1); $request->macro('userInfo', function () use (&$data) { return $data; });
-
-
复用通用方法片段
这是Trait最直接的用途。将多个类中重复出现的“代码片段”提取出来。
// 一个处理时间戳的Trait,很多模型都可能需要 trait TimeStampTrait { public function getCreateTimeTextAttr($value, $data) { return date('Y-m-d H:i:s', $data['create_time']); } public function setCreateTimeAttr($value) { return strtotime($value); } } // 在用户模型中复用 class UserModel { use TimeStampTrait; // 瞬间拥有了时间戳处理能力 // ... 其他用户相关的逻辑 } // 在商品模型中同样复用 class ProductModel { use TimeStampTrait; // 同上,无需重复编写 // ... } -
实现“多继承”效果
由于PHP是单继承,一个类无法同时继承两个父类。Trait可以模拟这种需求。
trait LoggableTrait {
public function log($message) {
// 写入日志的实现
file_put_contents('app.log', $message, FILE_APPEND);
}
}
trait CacheableTrait {
public function cache($key, $value) {
// 缓存操作的实现
Cache::set($key, $value);
}
}
// UserService 需要同时拥有日志和缓存能力
class UserService {
use LoggableTrait, CacheableTrait; // 组合多个“能力”
public function updateUser($id, $data) {
$this->log("开始更新用户 {$id}"); // 来自 LoggableTrait
// ... 更新逻辑
$this->cache("user_{$id}", $data); // 来自 CacheableTrait
}
}
作者:需要成长的小哥
出处:https://www.cnblogs.com/myDreamRealization/
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
如果希望更容易地发现我的新博客,记得在左下角点个“关注我”哦。(如有错误之处,还请指正!)
出处:https://www.cnblogs.com/myDreamRealization/
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
如果希望更容易地发现我的新博客,记得在左下角点个“关注我”哦。(如有错误之处,还请指正!)

浙公网安备 33010602011771号