hexin / library
hexin library for php projects
v5.9
2024-04-26 08:34 UTC
Requires
- php: >=7.2
Requires (Dev)
- dev-main
- v5.9
- v5.8
- v5.7
- v5.6
- v5.5
- v5.4
- v5.3
- v5.2
- v5.1
- v5.0
- v4.6
- v4.5
- v4.4
- v4.3
- v4.2
- v4.1
- v4.0
- v3.9
- v3.8
- v3.7
- v3.6
- v3.5
- v3.4
- v3.3
- v3.2
- v3.0
- v2.9
- v2.8
- v2.7
- v2.6
- v2.5
- v2.4
- v2.3.3
- v2.3.1
- v2.3.0
- v2.2.10
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.9
- v2.1.8
- v2.1.7
- v2.1.6
- v2.1.5
- v2.1.4
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.9
- v2.0.8
- v2.0.7
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v1.0.6
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
This package is auto-updated.
Last update: 2024-04-26 09:17:14 UTC
README
- Jobmessage 队列管理工具
- redis锁
- 一些helper类型:数组、日期、请求、字符串、导出csv类
- 审批流
- 导出xls类
- 文件导入任务
- 导出任务
- 工厂导出类
- 发送消息
安装:composer require hexin/library
一、Jobmessage 队列管理工具
①.杜绝事务回滚,但队列又执行的bug ②.担心事务没提交,设置队列的延迟时间过长的问题 ③.执行记录留痕
继承JobMessageModel,重写部分方法,比如insertJob等 ###1、创建表
CREATE TABLE `job_message` ( `id` int NOT NULL AUTO_INCREMENT, `merchant_id` int NOT NULL DEFAULT '0' COMMENT '商户id', `platform_id` int NOT NULL DEFAULT '0' COMMENT '平台id', `business_type` smallint NOT NULL DEFAULT '0' COMMENT '类型', `business_type_name` varchar(64) NOT NULL DEFAULT '' COMMENT '类型名称', `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '参数', `is_now` tinyint(1) NOT NULL DEFAULT '2' COMMENT '是否马上执行队列,1是2否', `fail_count` int NOT NULL DEFAULT '0' COMMENT '失败次数', `is_retry` tinyint(1) NOT NULL DEFAULT '2' COMMENT '重跑次数', `command_run_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '定时任务的运行开始时间(延迟队列可用)', `status` smallint NOT NULL DEFAULT '2' COMMENT '状态', `status_name` varchar(64) NOT NULL DEFAULT '' COMMENT '状态名称', `update_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `start_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '开始时间', `end_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '结束时间', `remark` varchar(255) NOT NULL DEFAULT '' COMMENT '备注', PRIMARY KEY (`id`), KEY `business_type` (`business_type`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
###2、插入队列
<?php namespace App\Test; use Hexin\Library\Model\JobMessageModel; class Test public function insertJob() { JobMessageModel::insertMsg( 2, JobMessageModel::BUSINESS_TYPE_EXAMPLE, $data ); } }
###3、处理队列,定时任务每秒执行
<?php namespace App\Console\Commands; use Hexin\Library\Model\JobMessageModel; use Hexin\Library\Traits\JobMessageCommand; use Illuminate\Console\Command; class JobMessage extends Command { use JobMessageCommand; /** * php artisan command:job_message * The name and signature of the console command. * * @var string */ protected $signature = 'command:job_message'; /** * @var string */ protected $description = '队列任务消费'; /** * Create a new command instance. */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $JobMessageModel = new JobMessageModel(); $query = $JobMessageModel->newQuery(); //待处理的任务 $query->whereIn('status', [ JobMessageModel::STATUS_WAIT ]); //指定任务类型 $query->whereIn('business_type', [ JobMessageModel::BUSINESS_TYPE_EXAMPLE ] ); $this->traitRunCommand($query); } public function traitGetRunStep() { return 200; } }
###4、处理失败的队列,定时任务,每秒执行
<?php namespace App\Console\Commands; use Hexin\Library\Model\JobMessageModel; use Hexin\Library\Traits\FailJobMessageCommand; use Illuminate\Console\Command; class FailJobMessage extends Command { use FailJobMessageCommand; /** * php artisan command:fail_job_message * The name and signature of the console command. * * @var string */ protected $signature = 'command:fail_job_message {id?}'; /** * The console command description. * * @var string */ protected $description = '失败的队列消息重跑'; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { //处理失败,可重试的任务 $Query = JobMessageModel::where([ ['status',JobMessageModel::STATUS_FAIL], ['is_retry',JobMessageModel::IS_YES] ]); $id = $this->argument('id'); if (!empty($id)) { $Query = $Query->where('_id', $id); } $this->traitRunCommand($Query); echo '完成'; } public function traitGetRunStep() { return 100; } }
二、redis锁
<?php namespace App\Test; use Hexin\Library\Cache\Redis\Lock; class Test public function lock() { $RedisKey = 'lock:123'; $Lock = new Lock(); //获取锁 if(!$Lock->getLocalLock($RedisKey,300)){ throw new ApiException([0,'正在执行,请稍后']); } try{ DB::beginTransaction(); //业务代码 DB::commit(); }catch (\Exception $e){ DB::rollBack(); //释放锁 Lock::releaseLock($RedisKey); throw new \Exception($e->getMessage()); } //释放锁 Lock::releaseLock($RedisKey); } }
三、导出csv类
<?php namespace App\Test; use Hexin\Library\Helpers\ExportCSVHelper; class Test public function csv() { $header = [ '姓名', '年龄', ]; $filename = '学生的年龄'; $path = '/app/exports/' . date('Y-m-d'); $ExportCSVHelper = new ExportCSVHelper($path,$filename,$header); $data = [ '张三','12岁' ]; $ExportCSVHelper->fwrite($data); $ExportCSVHelper->fclose(); } }
四、审批流
#### 审批配置 approval_process.php <?php return [ // 审批配置表 'approval_config_table_name' => 'hp_approval_config', // 审批泳道(等级)表 'approval_level_table_name' => 'hp_approval_level', // 审批节点设置表 'approval_process_table_name' => 'hp_approval_process', // 审批人表 'approval_process_user_table_name' => 'hp_approval_process_user', // 数据库连接名称,不填写则使用默认配置 'database_connection' => 'mysql', ]; <?php namespace App\Http\Repositories\Base; use App\Exceptions\ApiException; use App\Http\Repositories\BaseRepository; use App\Http\Repositories\Purchase\OrderApprovalRepository; use App\Http\Repositories\Purchase\OrderRepository; use App\Models\Approval\ApprovalConfigModel; use App\Models\Approval\ApprovalLevelModel; use App\Models\Approval\ApprovalProcessModel; use App\Models\Approval\ApprovalProcessUserModel; use App\Models\Discount\DiscountAccountStatementModel; use App\Models\Purchase\Order; use Illuminate\Support\Facades\Cache; // 审批流设置 class ApprovalConfigRepository extends BaseRepository { use \Hexin\Library\Traits\ApprovalConfigRepository; const TYPE_PURCHASE = 1; const TYPE_QC = 2; const TYPE_DISCOUNT = 4; const TYPE_SUPPLIER_RECONCILIATION = 3; public $type = [ self::TYPE_PURCHASE => '采购审批流', self::TYPE_QC => '质检审批流', // 供应商对账审批流 self::TYPE_SUPPLIER_RECONCILIATION => '供应商对账审批流', self::TYPE_DISCOUNT => '折扣单流水审批流', ]; // 重写 应用至所有待审批 public function applyToPending($data) { // 应用至所有待审批 todo $order_list = (new Order())->where('status', OrderRepository::STATUS_SUBMIT)->get(); if (!$order_list->isEmpty()) { foreach ($order_list as $item) { $item->orderApproval()->delete(); try { // 创建订单审批流 OrderApprovalRepository::createOrderApproval($item); } catch (\Exception $e) { throw new ApiException([ApiException::DEFAULT_ERROR_CODE, $e->getMessage()]); } } } } }
五、导出xls类
<?php namespace App\Test; use Hexin\Library\Helpers\ExportXLSHelper; class Test /** * 逐行写入数据 导出 */ public function testWriteData() { $fieldArr = ['id' => 'ID', 'name' => '名称']; // 表头 $file_name = '文件名'; $list = [ [ 'id' => 1, 'name' => '名称' ], [ 'id' => 2, 'name' => '名称2' ] ]; $file_name = $file_name . '.xlsx'; $XLSWriteExcelExport = (new ExportXLSHelper($fieldArr, $file_name)); foreach ($list as $v) { $XLSWriteExcelExport->writeData($v); } $filePath = $XLSWriteExcelExport->store(); return response()->download($filePath, $file_name, $headers = ['Content-Type' => 'application/vnd.ms-excel;charset=utf-8']); } /** * 一次性写入数据 导出 */ public function testWriteDataList() { $fieldArr = ['id' => 'ID', 'name' => '名称']; // 表头 $file_name = '文件名'; $list = [ [ 'id' => 1, 'name' => '名称' ], [ 'id' => 2, 'name' => '名称2' ] ]; $file_name = $file_name . '.xlsx'; $XLSWriteExcelExport = (new ExportXLSHelper($fieldArr, $file_name)); $XLSWriteExcelExport->writeDataList($list); $filePath = $XLSWriteExcelExport->store(); return response()->download($filePath, $file_name, $headers = ['Content-Type' => 'application/vnd.ms-excel;charset=utf-8']); } }
六、文件导入
###1、创建表
CREATE TABLE `file_import_task` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `handle_status` tinyint unsigned NOT NULL DEFAULT '1' COMMENT '1 待处理 20校验数据中 21数据校验失败 22数据校验通过 30等待数据导入,31 数据导入中 32 部分数据导入 33数据导入完成 34导入失败 40 业务处理中 41部分完成 42已完成', `business_type` int NOT NULL COMMENT '业务类型', `original_file_name` varchar(100) NOT NULL COMMENT '原文件名', `fail_msg` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '错误原因', `merchant_id` int unsigned NOT NULL COMMENT '商户id', `admin_uuid` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '操作人uuid', `admin_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '操作人', `update_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '数据更新时间', `create_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT '数据添加时间', `save_file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '保存文件完整路径', `save_file_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '保存的文件名', `read_total_rows` int NOT NULL COMMENT '代码获取到的行数 不一定是真正有效的行数 ', `file_size` int unsigned NOT NULL COMMENT '文件大小 bytes', `import_start_time` int unsigned NOT NULL DEFAULT '0' COMMENT '导入开始时间', `import_end_time` int unsigned NOT NULL DEFAULT '0' COMMENT '导入结束时间', `server_local_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '服务器本地路径', `related_condition1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '关联条件1 根据各自业务去存', `related_condition2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '关联条件2 根据各自业务去存', `related_condition3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '关联条件3 根据各自业务去存', `remark` varchar(255) NOT NULL COMMENT '备注', `success_num` int NOT NULL COMMENT '成功数量', `fail_num` int NOT NULL COMMENT '失败数量', `total_nums` int NOT NULL COMMENT '总数量', `data_start_time` int NOT NULL COMMENT '数据开始时间', `data_end_time` int NOT NULL COMMENT '数据结束时间', PRIMARY KEY (`id`) USING BTREE, KEY `handle_status` (`business_type`,`handle_status`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='文件导入任务';
七、导出任务
###1、配置yar-services.php,新增'ExpertListServices'
return [ 'storage' => [ 'path' => env('STORAGE_URL', '127.0.0.1').'/yar/', 'services' => [ 'ExpertListServices' => 'ExpertListServices', ] ], ]; ?php>
###2、创建导出任务
<?php namespace App\Console\Commands\Export; use Hexin\Library\Model\ExportJobModel; use Illuminate\Console\Command; use Hexin\Library\Traits\ExportDataTrait; use App\Libs\Helpers\ExportCSVHelper; class ExportTask extends Command { /** * 创建导出任务 * @throws \Exception */ public function export() { //create export ExportJobModel::createExportJob( $type,//类型,仓储的type $filename,//导出文件名 $params,//条件 [ 'template_type' => 'exportExample',//模板类型 'class_name' => __CLASS__,//导出的类,一般是当然类 'method' => 'exportExampleData',//导出的方法 'dir_name' => 'olap',//导出存储的目录,app/exports/dir_name/2024-01-01 ] ); } /** * 导出数据 * @throws \Exception */ public final exportExampleData($params, $path, $file_name) { $header = [ 'id', '名称', ]; $exportCSVHelper = new ExportCSVHelper($path, $filename, $header); $query = (new Model())->getQuery($params); $query->chunkById(10000, function ($chunk) use ($exportCSVHelper) { foreach ($chunk as $item) { $row = []; foreach ($item as $field => $val) { $row[] = $value; } $exportCSVHelper->fputCsv($row); } }); $exportCSVHelper->fclose(); } } ?php>
###3、创建定时任务,每秒执行
<?php namespace App\Console\Commands\Export; use Hexin\Library\Model\ExportJobModel; use Illuminate\Console\Command; use Hexin\Library\Traits\ExportDataTrait; class ExportTask extends Command { use ExportDataTrait; /** * php artisan command:export_task * The name and signature of the console command. * * @var string */ protected $signature = 'command:export_task {template_type?}'; /** * The console command description. * * @var string */ protected $description = '导出任务,每分钟执行一次'; /** * 模板类型 * @var string[] */ public static $template_type = [ 'exportExample', ]; /** * Create a new command instance. * * @return void */ public function __construct() { parent::__construct(); } /** * Execute the console command. * * @return mixed */ public function handle() { $template_type = $this->argument('template_type'); if (!$template_type) { $template_type = array_map(function ($item) { return "'{$item}'"; }, self::$template_type); $template_type = implode(',', $template_type); } else { $template_type = "'{$template_type}'"; } $params = [ 'where' => "template_type in ({$template_type}) and handling_status=" . ExportJobModel::HANDLING_STATUS_WAIT, ]; $ErpExportTasks = ExportJobModel::getStorageExport($params); //默认rpc获取任务,可传第二个参数,从指定模型读取 if (!$ErpExportTasks) { $this->info('没有导出任务'); return; } $this->traitRunCommand($ErpExportTasks);//默认rpc获取任务,可传第二个参数,从指定模型读取和导出 return true; } } ?php>
八、工厂导出类
<?php namespace App\Test; use Hexin\Library\Helpers\ExportFactory; class Test /** * 逐行写入数据 导出 */ public function export() { $query = [];//查询的query $path = 'app/exports/test' . date('Y-m-d');//文件存放的文件夹 eg:是导出脚本(ExportDataTrait.php)传过来的path $fileName = 'test';//文件名称(不包含文件格式后缀) eg:是导出脚本(ExportDataTrait.php)传过来的文件名称 $header = ['title_1' => '标题1', 'title_2' => '标题2'];//表格标题 $driver = 'xls'; //文件格式类型:csv, xls //创建导出类工厂实例 $exportFactory = new ExportFactory($path, $fileName, $header, $driver); //插入数据 $query->chunk(500, function ($itemArr) use ($exportFactory) { $itemArr = collect($itemArr)->toArray(); foreach ($itemArr as $item) { $exportFactory->fwrite($itemData); } }); //获取文件地址(不包含域名) $filePath = $exportFactory->getFilePath(); //保存文件 $exportFactory->fclose(); return $filePath; } }
九、发送消息
###1、config目录下,新增配置文件message_notice
return [ 'dingding'=>[//钉钉 'error'=>[ 'webhook' => '',//机器人的地址 'secret' => '',//机器人的secret 'mobiles' => [],//@的人 ], 'info'=>[ 'webhook' => '', 'secret' => '', 'mobiles' => [], ], ] ];
###2、发送消息
<?php namespace App\Test; use Hexin\Library\Helpers\MessageHelper; class Test { /** * 逐行写入数据 导出 */ public function testExportBusiness() { MessageHelper::sendText('消息内容','dingding'); } }