# supplier **Repository Path**: CiJiu/supplier ## Basic Information - **Project Name**: supplier - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-29 - **Last Updated**: 2025-12-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 一. 数据访问权限设计方案 核心思路 - 权限规则抽象化:将复杂权限需求转化为可配置的规则组 - 部门树动态解析:通过接口获取实时部门结构并缓存 - 精确到人的控制:支持部门/个人混合权限模式 - 高效查询机制:基于预处理的权限组快速过滤数据 include:定义允许访问的范围(白名单) exclude:定义明确禁止访问的范围(黑名单) ```json { "include": { "departments": [2, 5], // 允许访问的部门ID列表 "users": [101, 102], // 允许访问的用户ID列表 "recursive": true // 是否递归包含子部门 }, "exclude": { "departments": [3], // 禁止访问的部门ID列表 "users": [103] // 禁止访问的用户ID列表 } } ``` 通过 include 和 exclude 的灵活组合,可以精确控制用户的数据访问权限: 部门级控制:通过 departments 数组指定允许或禁止的部门范围(中台的部门) 个人级控制:通过 users 数组实现对特定用户的细粒度授权(此系统的用户) 层级控制:通过 recursive 参数决定是否包含子部门数据 优先级处理:exclude 优先级高于 include,确保敏感数据不会被意外访问 注:接口需要数据权限控制,需要在路由增加中间件 ->middleware('DataPermission') , 然后使用:Illuminate\Http\Request $request->allowed_user_ids 获取当前用户的权限过滤后的用户ID列表 举例: $data = $model::whereIn('user_id', $request->allowed_user_ids)->get();// 查询数据(自动应用权限) 上述可以符合以下需求: 1. B部门B1人员 ,能看B,F,C整个部门下所有人员的数据,D,G,...都不能看 2. B部门B2人员 ,能看B1,B2,B4,F1,G2,C1 各用户的数据,其它人的数据都不能看 3. C部门C1人员 ,能看A部门组织下面全部人员的数据 4. C部门C2人员 ,能看B部门与G部门下全部人员数据与D2,D3,D5,C3各人员的数据 ABCDFG 是部门,上下级关系树也如下,root是根目录,A与C是一级部门,部门是无限极: ``` root: -A ----B (B1,B2,B3,B4,...)//人员 ----D (D1,D2,D3,D4,D5,...)//人员 ----F (F1,F2,F3,...)//人员 -C (C1,C2,C3,...)//人员 ----G (G1,G2,G3,...)//人员 ``` 此方案满足所有需求,实现了精确到个人的权限控制,同时保持系统灵活性和高性能,通过中间件机制无缝集成到现有系统,权限变更无需修改业务代码。 ### 二. 其他内容 1. ->middleware('throttle.requests') 这个是指定路由是否增加防抖 , 180s/1次 2. 所有的model层最都继承了CoreBaseModel类,里面实现了所有的事件,处理数据,模拟模型事件机制,让你能够在 Laravel 中享受到类似的开发体验 ### 三. 清除路由缓存 php artisan route:clear php artisan config:clear //查看注册路由列表 php artisan route:list ### 四. 数据库表设计规范 1. 全表(dept_id,person_id,company_id,srm_uid)固定字段,新建表时,必须有这个四个字段, 2. 插入与编辑数据时候要使用 BaseService 中的 createBatch 或 create 方法,这样会自动处理 dept_id,person_id,company_id,srm_uid 字段。如果不想用这个方法,可以自己在Service中处理,必须调用这个方法($info = $this->checkParams($params, $model);) ### 五. 数据查询(携带固定参数查询[company_id,supplier_id,person_id]) 方式一: $req = self::getWhere($req , $params); $query = $model::useDiyWheres($req); 方式二(将上述合并方法,尽量使用这个): $query = $model::builderQuery($req , $params , $options); ### 六. elasticsearch 查询与使用(继承我的 BaseModelEs 类,然后实现里面的方法即可使用,查询方法都是orm模式,可以链式操作的) ``` $data = OperationLogModelEs::where('id', '=', 683)->where('srm_uid', '=', 6)->get(); $data = OperationLogModelEs::find(683); $data = OperationLogModelEs::paginate(1, 2); ... ``` ### 七:正式服与测试服(公网) ``` 正式服:https://srm.georgebuilder.com/api 测试服:https://srm.georgebuilder.com/testapi 举例: $path = '/users/users/login'; https://srm.georgebuilder.com/api + $path https://srm.georgebuilder.com/testapi + $path testapi = 代表走的是测试服dev分支代码 api = 代表走的是正式服master分支代码 注:RouteServiceProvider.php 里面的boot方法要设置好正式还是测试,最好2个分支代码在同一个目录下,然后去配 nginx 访问不同目录的入口文件 ``` ### 八:消息队列 Laravel 原生队列表:jobs 与 failed_jobs Laravel 默认只会在第一次执行 php artisan queue:table 和 php artisan queue:failed-table 时生成 jobs 与 failed_jobs 的迁移文件;随后必须手动运行 php artisan migrate,这两个表才会真正出现在数据库里,框架本身不会“自动”建表。 ### 九:laravel 下使用 swoole , 详细对比一下 SupplierController 继承 ApiController 与 SwooleController 两种环境的区别 - 安装swoole与使用 * 直接安装宝塔的swoole6版本 , 不要装6以下的版本 * 启动命令:php artisan swoole:http --port=8080 * 自行添加 supervisor 守护进程 1. 运行环境区别 - 继承 ApiController(传统环境) - 运行方式:传统的 PHP-FPM/Apache 模式 - 进程模型:每个请求创建新进程,请求结束后销毁 - 内存管理:请求级隔离,每次请求重新初始化 - 并发处理:依赖进程池,资源消耗大 - 继承 SwooleController(Swoole环境) - 运行方式:基于 Swoole HTTP 服务器 - 进程模型:常驻内存,Worker 进程复用 - 内存管理:常驻内存,需要注意内存泄漏 - 并发处理:协程模式,高并发性能好 2. 性能差异 - ApiController 性能特点(每次请求都要) 1. 重新加载框架 2. 重新建立数据库连接 3. 重新初始化所有服务 4. 请求结束后释放所有资源 - SwooleController 性能优势(常驻内存优势) 1. 框架只需启动一次 2. 数据库连接可复用 3. 服务对象可缓存 4. 避免重复初始化开销 3. 功能差异 | 功能特性 | ApiController | SwooleController | |:-----|:-----|:-----| | 异步处理 | ❌ 不支持 | ✅ 支持 $this->async() | | 协程支持 | ❌ 不支持 | ✅ 支持协程并发 | | 性能监控 | ❌ 无内置监控 | ✅ 自动性能记录 | | Worker管理 | ❌ 无 | ✅ 获取Worker ID | | 协程追踪 | ❌ 无 | ✅ 获取协程ID | | 内存监控 | ❌ 基础监控 | ✅ 详细内存跟踪 | 4. 代码示例对比 - 传统方式(继承ApiController) ``` class SupplierController extends ApiController { public function getPageList(Request $request) { // 同步处理,阻塞执行 $params = self::getParams($request); $result = self::getService()->getPageList($params, self::getModel()); [$list, $total, $tabs] = $result; return ApiResponse::pagination($list, $total, $tabs); } } ``` - Swoole方式(继承SwooleController) ``` class SupplierController extends SwooleController { public function getPageList(Request $request) { $params = self::getParams($request); // 异步处理,非阻塞 $result = $this->async(function () use ($params) { return self::getService()->getPageList($params, self::getModel()); }); [$list, $total, $tabs] = $result; return ApiResponse::pagination($list, $total, $tabs); } // 自动性能记录,无需手动调用 // 内存使用监控 // 协程信息追踪 } ``` 5. 适用场景 - 选择 ApiController 当 * 项目规模较小,并发要求不高 * 开发团队熟悉传统PHP开发 * 需要快速部署,无需复杂配置 * 对性能要求不是特别苛刻 - 选择 SwooleController 当 * 需要处理高并发请求 * 有异步处理需求(如:调用多个API、数据库查询优化) * 需要实时性能监控 * 追求极致性能优化 * 微服务架构中的高性能组件 6. 切换建议 - 如果追求性能:使用 SwooleController * 自动性能监控 * 异步处理能力 * 更高的并发处理能力 - 如果稳定性优先:暂时使用 ApiController * 成熟稳定,问题少 * 开发调试简单 * 无内存泄漏风险 7. 总结 SwooleController 是 Laravel 的 Swoole 扩展,提供了异步处理、协程支持、性能监控等特性,可以帮助开发者更高效地处理高并发请求。 只需要修改继承关系,就能获得所有 Swoole 的优势功能。 ### 十.查询 1. 针对es与mysql的json字段查询如下: ``` if (!empty($req['dept_ids'])) { #这里是或 json_or(对数组每个值匹配) , 并且是json_and(对整个数组匹配) $where[] = ['dept_ids', 'json_or', $req['dept_ids']]; } ``` ### 十一. sh 脚本(脚本目录:app/Console/Bash) 要统一用 www 或 root 用户进行启动,看你手动执行启动用的什么用户,用不同用户启动会产生多个相同进程,还杀不掉(权限问题,脚本不可能绕过操作系统权限帮非 root 杀掉 root 的进程) 计划任务调度器: ```bash chmod +x app/Console/Bash/start_task_run_nohup.sh ./start_task_run_nohup.sh start 【启动】 ./start_task_run_nohup.sh status 【查看状态】 ./start_task_run_nohup.sh stop 【停止】 ./start_task_run_nohup.sh restart 【重启】 ./start_task_run_nohup.sh up 【启动+重启】 日志:`storage/logs/sh/task_run.nohup.log` PID:`storage/logs/sh/task_run.pid` ``` ### 十二. 自动生成数据库迁移文件(make:migrations) 命令定义在:`app/Console/Commands/GenerateMigrationsFromDatabase.php` ```bash # 使用默认数据库连接,生成当前库中所有表的迁移文件 php artisan make:migrations # 指定数据库连接(对应 config/database.php 里的 connection 名称) php artisan make:migrations --connection=mysql # 指定迁移文件输出目录(相对项目根目录) php artisan make:migrations --path=database/migrations/generated ``` 说明: - 每张表对应一个迁移文件:`0000_00_00_000000_create_{table}_table.php` - 每次运行会根据**当前数据库表结构**覆盖生成迁移文件(字段类型、默认值、字段注释、索引) - 如果某张表在数据库里已经删除,对应的 `0000_00_00_000000_create_{table}_table.php` 会自动被删除 - 这些迁移可以单独执行: ```bash php artisan migrate --path=database/migrations/generated ``` * 问题:为什么生成的 class 是 return new class,还有文件名前缀0000_00_00_000000_create_item_purchase_table 这样的了,而不是时间? - 两个都是我在设计这个生成器时“故意”这样做的,目的是方便你 反复覆盖生成 ,避免各种迁移类名 / 文件名冲突,不是 Laravel 自带限制。 1. 为啥是 return new class extends Migration - 这是 Laravel 8 之后推荐的“匿名迁移”(anonymous migration)写法,框架层面完全支持这种写法,你当前项目里用 php artisan migrate 跑也没问题,用 return new class 是为了让“自动覆盖生成”这件事更安全,不用担心类名重复 2. 为啥文件名前缀是 0000_00_00_000000_... 而不是时间戳 - 迁移文件可以被重新覆盖生成最新的