mirror of
https://gitee.com/ctexthuang/hyperf_rbac_framework_server_ctexthuang.git
synced 2025-12-25 12:33:46 +08:00
282 lines
8.5 KiB
Markdown
282 lines
8.5 KiB
Markdown
## 仓库
|
||
|
||
- [hyperf_rbac_framework_server_ctexthuang](https://gitee.com/ctexthuang/hyperf_rbac_framework_server_ctexthuang.git) - git远程仓库地址
|
||
|
||
## 特性
|
||
|
||
- **最新技术栈**:使用 PHP8.3/hyperf3.1/swoole5.1.4/phpredis 6.0.2 等后端前沿技术开发
|
||
|
||
## 文档
|
||
|
||
[文档地址 Github](https://hyperf.wiki/3.1/)
|
||
|
||
## 前序准备
|
||
|
||
- [php8.3](https://www.php.net/) 和 [git](https://git-scm.com/) - 项目开发环境
|
||
- [swoole](https://www.swoole.com/) - 熟悉 swoole 特性
|
||
- [php8.3](https://www.php.net/) - 熟悉 php 基础语法
|
||
- [hyperf](https://hyperf.wiki/3.1/) - 熟悉 `hyperf` 基本语法
|
||
## 安装和使用
|
||
|
||
- 安装 swoole 和 phpredis 扩展
|
||
|
||
```
|
||
自行搜索安装教程
|
||
```
|
||
|
||
- 获取代码
|
||
|
||
```bash
|
||
git clone https://gitee.com/ctexthuang/hyperf_rbac_framework_server_ctexthuang.git
|
||
```
|
||
|
||
- vendor
|
||
|
||
```bash
|
||
composer install
|
||
```
|
||
|
||
- 运行
|
||
|
||
```bash
|
||
cp .env.example .env
|
||
|
||
vim .env
|
||
|
||
php bin/hyperf.php start
|
||
```
|
||
|
||
- command 函数
|
||
```bash
|
||
#框架自有 php bin/hyperf.php + 以下
|
||
gen:amqp-consumer Create a new amqp consumer class
|
||
gen:amqp-producer Create a new amqp producer class
|
||
gen:aspect Create a new aspect class
|
||
gen:class Create a new class
|
||
gen:command Create a new command class
|
||
gen:constant Create a new constant class
|
||
gen:controller Create a new controller class
|
||
gen:job Create a new job class
|
||
gen:kafka-consumer Create a new kafka consumer class
|
||
gen:listener Create a new listener class
|
||
gen:middleware Create a new middleware class
|
||
gen:migration Generate a new migration file
|
||
gen:model Create new model classes.
|
||
gen:nats-consumer Create a new nats consumer class
|
||
gen:nsq-consumer Create a new nsq consumer class
|
||
gen:process Create a new process class
|
||
gen:repository Create a new repository class
|
||
gen:request Create a new form request class
|
||
gen:resource create a new resource
|
||
gen:seeder Create a new seeder class
|
||
gen:service Create a new service class
|
||
|
||
#新增命令
|
||
php bin/hyperf.php gen:service LoginService
|
||
php bin/hyperf.php gen:repository OssRepository
|
||
```
|
||
|
||
## Git 贡献提交规范
|
||
|
||
- `feat` 新功能
|
||
- `fix` 修补 bug
|
||
- `docs` 文档
|
||
- `style` 格式、样式(不影响代码运行的变动)
|
||
- `refactor` 重构(即不是新增功能,也不是修改 BUG 的代码)
|
||
- `perf` 优化相关,比如提升性能、体验
|
||
- `test` 添加测试
|
||
- `build` 编译相关的修改,对项目构建或者依赖的改动
|
||
- `ci` 持续集成修改
|
||
- `chore` 构建过程或辅助工具的变动
|
||
- `revert` 回滚到上一个版本
|
||
- `workflow` 工作流改进
|
||
- `mod` 不确定分类的修改
|
||
- `wip` 开发中
|
||
- `types` 类型
|
||
|
||
## 日志(合理安排)
|
||
| 分组名称 | 用途 | 日志级别 | 保留天数 | 备注 |
|
||
|---------|---------|------------|------|----------|
|
||
| app | 应用业务日志 | DEBUG/INFO | 7 | 主要业务逻辑日志 |
|
||
| error | 错误日志 | ERROR | 30 | 只记录错误 |
|
||
| cache | CACHE日志 | DEBUG | 3 | 开发调试用 |
|
||
| request | 请求访问日志 | INFO | 15 | 记录所有请求 |
|
||
| cron | 定时任务日志 | INFO | 30 | 定时任务执行记录 |
|
||
| payment | 支付相关日志 | INFO | 90 | 重要财务数据 |
|
||
| audit | 审计日志 | INFO | 365 | 重要操作记录 |\
|
||
|
||
```php
|
||
//注入这个类
|
||
use App\Lib\Log\Logger;
|
||
|
||
$this->logger->cache()->error(...),
|
||
```
|
||
|
||
## 缓存
|
||
```php
|
||
//注入这个类
|
||
use App\Cache\Redis\RedisCache
|
||
|
||
$this->redis->with($poolName)->exists($key)
|
||
//$poolName 配置在 config/autoload/redis.php 在 default下面追加即可 看官网
|
||
|
||
//lua调用涉及多文件请看示例
|
||
|
||
$this->redis->with($poolName ?? 'default')->lua(RateLimit::class)->check($argument);
|
||
//lua()里面是App\Cache\Redis\Lua\*文件 后面跟的方法是 该文件的方法
|
||
//我做了返回类型补全 可以直接IDE跳转查看参数
|
||
```
|
||
|
||
## tips
|
||
|
||
1.AdminService类必须继承BaseAdminService
|
||
```php
|
||
//例子 app/Service/Admin/AdminUser/UserService
|
||
class UserService extends \App\Service\Admin\BaseAdminService {
|
||
|
||
}
|
||
|
||
//由于在 app/Controller/Admin/AdminUserController 中 service 是 注解注入的 所以 BaseAdminService只会实例化一次(单例)
|
||
class AdminUserController extends AbstractController
|
||
{
|
||
/**
|
||
* @var UserService
|
||
*/
|
||
#[Inject]
|
||
protected UserService $service;
|
||
|
||
/**
|
||
* @return array
|
||
*/
|
||
#[RequestMapping(path: "getInfo", methods: "GET")]
|
||
public function getInfo(): array
|
||
{
|
||
return $this->service->handle();
|
||
}
|
||
}
|
||
|
||
//所以在service中获取上下文的数据必须重置获取而不能存入BaseService属性中拿取
|
||
//假设在 Api目录中写 BaseApiService请务必注意
|
||
class UserService extends \App\Service\Admin\BaseAdminService {
|
||
/**
|
||
* @param string $name
|
||
* @return \current_admin_id|mixed
|
||
*/
|
||
public function __get(string $name)
|
||
{
|
||
if ($name === 'adminId') return Context::get('current_admin_id',0);
|
||
|
||
if (!property_exists($this, $name)) throw new ErrException('属性未定义');
|
||
|
||
return $this->$name;
|
||
}
|
||
}
|
||
|
||
class UserService extends BaseAdminService{
|
||
public function handle()
|
||
{
|
||
return $this->adminId;
|
||
}
|
||
}
|
||
// 或者在controller中实例化去调用
|
||
class AdminUserController extends AbstractController
|
||
{
|
||
/**
|
||
* @return array
|
||
*/
|
||
#[RequestMapping(path: "getInfo", methods: "GET")]
|
||
public function getInfo(): array
|
||
{
|
||
return (new UserService)->handle();
|
||
}
|
||
}
|
||
```
|
||
|
||
2.controller必须增加ResponseFormat注解
|
||
```php
|
||
//示例 : app/Controller/Admin/AdminUserController
|
||
|
||
#[Controller(prefix: "admin/adminUser")]
|
||
#[ResponseFormat('admin')]
|
||
#[Middleware(middleware: AdminTokenMiddleware::class, priority: 100)]
|
||
#[Middleware(middleware: PermissionMiddleware::class, priority: 99)]
|
||
class AdminUserController extends \App\Controller\AbstractController{
|
||
|
||
}
|
||
|
||
//因为在涉及到公有抛出 ErrException或者 验证器抛出 的时候 会根据不同的注解 返回不同的 Return
|
||
class BaseErrExceptionHandler extends ExceptionHandler{
|
||
public function handle()
|
||
{
|
||
// 从注解获取响应格式(优先于路径解析)
|
||
$format = $this->request->getAttribute('response_format') ?? $this->repairResponseFormatByPath();
|
||
|
||
// 动态选择策略
|
||
$returnClass = match ($format) {
|
||
'admin', 'common' => AdminReturn::class,
|
||
'api' => ApiReturn::class,
|
||
default => null,
|
||
};
|
||
}
|
||
}
|
||
|
||
// 通过切面存入
|
||
class ResponseFormatAspect extends AbstractAspect
|
||
{
|
||
// 获取注解定义的格式
|
||
$annotation = $proceedingJoinPoint->getAnnotationMetadata()->class[ResponseFormat::class]
|
||
?? $proceedingJoinPoint->getAnnotationMetadata()->method[ResponseFormat::class] ?? null;
|
||
|
||
if ($annotation) {
|
||
// 将注解格式存入请求属性(覆盖中间件的默认值)
|
||
$request = $proceedingJoinPoint->arguments['request'] ?? null;
|
||
if ($request instanceof Request) {
|
||
$request->withAttribute('response_format', $annotation->format);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
3.token的使用要分模块
|
||
```php
|
||
//示例 app/Service/Admin/Login/LoginService
|
||
use App\Service\BaseTokenService $tokenService
|
||
|
||
class LoginService extends \App\Service\Admin\BaseAdminService{
|
||
public function handle()
|
||
{
|
||
$jwtHandle = $this->tokenService->setJwt('admin')->getJwt();
|
||
|
||
return $this->adminReturn->success('success',[
|
||
'access_token' => $jwtHandle->builderAccessToken((string) $adminInfo->id)->toString(),
|
||
'refresh_token' => $jwtHandle->builderRefreshToken((string) $adminInfo->id)->toString(),
|
||
'expire_at' => (int) $jwtHandle->getConfig('ttl', 0),
|
||
]);
|
||
}
|
||
}
|
||
//setJwt函数里面类似$poolName 设置在 config/autoload/jwt.php 未设置属性可复用 default 设置
|
||
```
|
||
|
||
4.引入 Repository层架构 解放 model层压力 model 只管理数据模型和关联
|
||
```php
|
||
//详细请看app/Common/Repository 文件下的文件 示例 app/Service/Admin/Login/LoginService
|
||
|
||
class LoginService extends \App\Service\Admin\BaseAdminService{
|
||
|
||
/**
|
||
* 需要提前注入
|
||
* @var AdminUserRepository
|
||
*/
|
||
#[Inject]
|
||
protected AdminUserRepository $userRepository;
|
||
|
||
public function handle()
|
||
{
|
||
$adminInfo = $this->userRepository->findByUserName((string)$this->request->input('username'));
|
||
}
|
||
}
|
||
```
|
||
|
||
5.公用类都在 app/Common 下面 包括 `Interface`、`Macros`、`Repository`、`Trait`
|
||
|
||
6.后台权限注解 #[Permission] 和 #[PermissionMiddleware] |