php中使用empty/unset去清空变量的warning

本文探讨了PHP中使用empty()和unset()函数检查与移除变量的正确方式,并提供了具体的代码示例进行说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Note: empty()/unset() only checks variables as anything else will result in a parse error. In other words, the following will not work: empty(trim($name)).

所以

if(!$this->odwp_empty() &&
            array_key_exists($action->odwp_get_key())){
            unset($action->odwp_get_key());
}

要变成

$key = $action->odwp_get_key();
if(!$this->odwp_empty() &&
            array_key_exists($key)){
            unset($key);
}
public function ReverseDeliveryFeeVerifyDo($yearMonth): bool { $monthTimeRange = $this->getMonthTimeRange($yearMonth); // 一次性查询出逆向配送费报价表数据 避免重复查询数据库 $quoteList = QuoteModel::field('warehous,price')->select()->toArray(); $quoteMap = []; if (!empty($quoteList)) { $quoteMap = array_column($quoteList, 'price', 'warehous'); } else { //Log::warning('【逆向配送费核对仓库名称不匹配】--月份为:' . $yearMonth . "的费用核对匹配不到逆向配送费报价表的仓库名称"); return false; } $status = true; // 初始化状态 $itemizationModel = new ItemizationModel(); $batchCount = 0; // 批次计数器 $reconnectInterval = 50; // 每100批重连一次 try { // 使用chunk方法分批处理数据,每批处理50条 ItemizationModel::whereBetween('business_time', [ $monthTimeRange['startTime'], $monthTimeRange['endTime'] ])->field('id,billing_amount,warehouse_name,theoretical_amount,fee_difference')->chunk(5, function ($items) use ($yearMonth, $quoteMap, &$status, $itemizationModel, &$batchCount, $reconnectInterval) { // 批次计数递增 $batchCount++; // 达到重连间隔时,重新连接数据库 // if ($batchCount % $reconnectInterval === 0) { // $this->reconnectDatabase(); // //Log::info("【数据库重连】已处理{$batchCount}批,重新连接数据库"); // } foreach ($items as $item) { $updateData = []; if (!empty($item->warehouse_name) && isset($quoteMap[$item->warehouse_name])) { $updateData['theoretical_amount'] = $quoteMap[$item->warehouse_name]; $updateData['fee_difference'] = $item->billing_amount - $quoteMap[$item->warehouse_name]; } else { $updateData['theoretical_amount'] = null; $updateData['fee_difference'] = null; } // 单条更新替代批量saveAll Db::table('la_reverse_delivery_fee') ->where('id', $item->id) ->update($updateData); unset($updateData); // 及时释放内存 } // 释放批次数据内存并触发垃圾回收 unset($items); gc_collect_cycles(); }); } catch (\Exception $e) { print_r("报错了直接干死整个进程,具体报错信息如下:".$e->getMessage());die; //Log::error('【逆向配送费核对异常】--月份为' . $yearMonth . "的费用核对发生错误:" . $e->getMessage()); $status = false; } // 释放主函数中的大型变量 unset($quoteList, $quoteMap, $itemizationModel); gc_collect_cycles(); return $status; } 通过我这种写法 我的mysql容器的内存飙升到了95% 然后就报上面的错误了 难道和我的mysql容器资源耗尽有关系吗?
07-06
<?php namespace app\common\service\wareHousFee\jingdong\wareHousingFees; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesItemizationModel; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesItemVeryModel; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesQuoteModel; use app\common\model\wareHousFee\newFie\camelCaseFee\CamelCaseFeeItemizationModel; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; use think\facade\Log; class WareHousingFeesService { public function __construct(){} /** * @notes 京东仓储服务费核对逻辑 * @param $yearMonth * @return bool * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author 胡军 * @date 2025/06/27 */ public function wareHousingFeeVerifyDo($yearMonth):bool{ $monthTimeRange = $this->getMonthTimeRange($yearMonth); //获取时间范围内的数据并进行分组统计 //total_quantity 总数 //total_settlement_amount 总的结算金额 $itemizationMonthList = WareHousingFeesItemizationModel::whereBetween('business_time', [$monthTimeRange['startTime'], $monthTimeRange['endTime']]) ->field([ 'document_number', 'document_type', 'SUM(quantity) as total_quantity', 'SUM(settlement_amount) as total_settlement_amount' ]) ->group('document_number, document_type') ->select() ->toArray(); //一次性读取报价单避免foreach循环 提升效率 $quoteList = WareHousingFeesQuoteModel::select()->toArray(); $quoteListRst = []; foreach ($quoteList as $item) { $quoteListRst[$item['service_type']] = $item; } if(!empty($quoteListRst)){ foreach($itemizationMonthList as $key => $value){ //初始化理论金额为0 $itemizationMonthList[$key]['theoretical_amount'] = 0; if($value['document_type'] == '出库单' && !empty($quoteListRst['出库单'])){ //$value['total_quantity'] 数量 if($value['total_quantity'] <= 3){ //理论金额 $itemizationMonthList[$key]['theoretical_amount'] = $quoteListRst['出库单']['first_three_items']; } else { $itemizationMonthList[$key]['theoretical_amount'] = $quoteListRst['出库单']['first_three_items'] + ($value['total_quantity'] - 3) * $quoteListRst['出库单']['additional_items']; } } if($value['document_type'] == '退供单' && !empty($quoteListRst['退供单'])){ $itemizationMonthList[$key]['theoretical_amount'] = $quoteListRst['退供单']['first_three_items'] * $value['total_quantity']; } if($value['document_type'] == '退货单' && !empty($quoteListRst['退货单'])){ if($value['total_quantity'] <= 3){ $itemizationMonthList[$key]['theoretical_amount'] = $quoteListRst['退货单']['first_three_items']; } else { $itemizationMonthList[$key]['theoretical_amount'] = $quoteListRst['退货单']['first_three_items'] + ($value['total_quantity'] - 3) * $quoteListRst['退货单']['additional_items']; } } //正常计算出来的理论金额不应该是0 那么这个时候就要记录日志便于排查 if($itemizationMonthList[$key]['theoretical_amount'] == 0){ //echo $value['document_number'].PHP_EOL; Log::warning('【京东仓储服务费明细核对】--月份为:'.$yearMonth."的京东仓储服务费订单明细核对匹配不到京东仓储服务费报价表la_storage_service_quotes当中的类型,明细单据编号为".$value['document_number']); unset($itemizationMonthList[$key]); continue; }else{ //差异:结算金额-理论金额 $itemizationMonthList[$key]['balance'] = $value['total_settlement_amount'] - $itemizationMonthList[$key]['theoretical_amount']; } } //批量分批次更新数据库 $status = true; $batchSize = 50; // 每批10条记录 $totalCount = count($itemizationMonthList); $batchCount = ceil($totalCount / $batchSize); $itemizationModel = new WareHousingFeesItemVeryModel(); for ($i = 0; $i < $batchCount; $i++) { $batchData = array_slice($itemizationMonthList, $i * $batchSize, $batchSize); $documentNumbers = array_column($batchData, 'document_number'); // 提取当前批次的所有单据号 try { $itemizationModel->startTrans(); // 批量删除操作(根据单据号) if (!empty($documentNumbers)) { $itemizationModel->whereIn('document_number', $documentNumbers)->delete(); } // 使用批量更新替代循环单条更新 $itemizationModel->saveAll($batchData); $itemizationModel->commit(); } catch (\Exception $e) { $itemizationModel->rollback(); //记录日志 Log::error('【京东仓储服务费明细核对异常】--月份为:'.$yearMonth."的费用核对发生错误:" . $e->getMessage()); //其中一个批次数据处理失败则直接退出循环 不再继续执行后续批次的数据处理 报错给前端显示 $status = false; break; } } return $status; }else{ return false; } } /** * @notes 根据年月比如2025-05获取当月时间范围 精确到秒 (git有问题未解决 暂时无法写入common.php当中 临时放这) * @param string $yearMonth * @return array * @author 胡军 * @date 2025/06/27 */ private function getMonthTimeRange(string $yearMonth): array { // 验证输入格式 (YYYY-MM) if (!preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $yearMonth)) { throw new InvalidArgumentException('输入格式不正确,必须为YYYY-MM格式'); } list($year, $month) = explode('-', $yearMonth); // 构建开始时间 $startTime = "{$year}-{$month}-01 00:00:00"; // 使用DateTime类计算当月最后一天 $lastDay = (new \DateTime("{$year}-{$month}-01")) ->modify('last day of this month') ->format('d'); // 构建结束时间 $endTime = "{$year}-{$month}-{$lastDay} 23:59:59"; return [ 'startTime' => $startTime, 'endTime' => $endTime ]; } } 这是我原有的代码业务逻辑,后来我修改为了如下: <?php namespace app\common\service\wareHousFee\jingdong\wareHousingFees; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesItemizationModel; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesQuoteModel; use think\facade\Db; use think\facade\Log; class WareHousingFeeService { public function __construct(){} /** * @notes 京东仓储服务费核对逻辑 * @param $yearMonth * @return bool * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author 胡军 * @date 2025/06/27 */ public function wareHousingFeeVerifyDo(string $yearMonth): bool { // 1. 获取月份时间范围 $monthTimeRange = $this->getMonthTimeRange($yearMonth); if (!$monthTimeRange) { Log::error("无效的月份格式: {$yearMonth}"); return false; } // 2. 预加载报价数据 $quoteList = WareHousingFeesQuoteModel::where('service_type', 'IN', ['出库单', '退供单', '退货单']) ->column('first_three_items,additional_items', 'service_type'); //print_r($quoteList);die; /*Array ( [出库单] => Array ( [first_three_items] => 1.500 [additional_items] => 0.250 [service_type] => 出库单 ) [退供单] => Array ( [first_three_items] => 0.500 [additional_items] => 0.500 [service_type] => 退供单 ) [退货单] => Array ( [first_three_items] => 3.000 [additional_items] => 0.500 [service_type] => 退货单 ) )*/ if (empty($quoteList)) { Log::warning("京东仓储服务费报价表为空,月份: {$yearMonth}"); return false; } // 3. 配置参数(从环境变量获取或使用默认值) $batchSize = 500; // 批次大小即每次读取的数据条数 $reconnectInterval = 200; // 每10万条重新连接一次数据库(200批次=10万条) $gcInterval = 20; // 垃圾回收间隔 $updateCount = 0; // 处理计数 $batchCount = 0; // 批次计数 $status = true; // 整体状态 // 性能监控变量 $startTime = microtime(true); $startMemory = memory_get_usage(); try { // 4. 创建基础查询 $query = WareHousingFeesItemizationModel::whereBetween('business_time', [ $monthTimeRange['startTime'], $monthTimeRange['endTime'] ]); // 5. 分批次处理数据 $query->chunk($batchSize, function($items) use ( &$updateCount, &$batchCount, &$status, $quoteList, $reconnectInterval, $gcInterval, $yearMonth, $startTime, $startMemory ) { $batchCount++; //print_r($items->toArray());die; // 6. 分组统计(按单据号和单据类型分组) $groupedData = []; foreach ($items as $item) { $key = $item->document_number . '|' . $item->document_type; //echo $key; //ESL00000022972118012|出库单 //ESL00000022971633940|退货单 //ESL00000022971819716|退供单 //ESL00000022972118012|出库单 if (!isset($groupedData[$key])) { $groupedData[$key] = [ 'document_number' => $item->document_number, 'document_type' => $item->document_type, 'total_quantity' => 0, 'total_settlement_amount' => 0 ]; } $groupedData[$key]['total_quantity'] += $item->quantity;// 数量累加 $groupedData[$key]['total_settlement_amount'] += $item->settlement_amount;//结算金额累加 } /*echo "<pre>"; print_r($groupedData); echo "</pre>";die; Array ( [ESL00000022972118012|出库单] => Array ( [document_number] => ESL00000022972118012 [document_type] => 出库单 [total_quantity] => 4 [total_settlement_amount] => 3 ) [ESL00000022971633940|退货单] => Array ( [document_number] => ESL00000022971633940 [document_type] => 退货单 [total_quantity] => 1 [total_settlement_amount] => 1.5 ) [ESL00000022971819716|退供单] => Array ( [document_number] => ESL00000022971819716 [document_type] => 退供单 [total_quantity] => 1 [total_settlement_amount] => 0 ) )*/ // 7. 计算理论金额和差额 $updateData = []; foreach ($groupedData as $data) { //单据类型 $docType = $data['document_type']; //数量累加 $totalQty = $data['total_quantity']; //结算金额累加 $settlementAmount = $data['total_settlement_amount']; //理论金额 $theoreticalAmount = 0; //判断类型 根据报价单以及数量 拿到具体的首三件以及大于三件的具体价格进行计算 switch ($docType) { case '出库单': if (isset($quoteList['出库单'])) { $quote = $quoteList['出库单']; $theoreticalAmount = ($totalQty <= 3) ? $quote['first_three_items'] : $quote['first_three_items'] + ($totalQty - 3) * $quote['additional_items']; } break; case '退供单': if (isset($quoteList['退供单'])) { $quote = $quoteList['退供单']; $theoreticalAmount = $quote['first_three_items'] * $totalQty; } break; case '退货单': if (isset($quoteList['退货单'])) { $quote = $quoteList['退货单']; $theoreticalAmount = ($totalQty <= 3) ? $quote['first_three_items'] : $quote['first_three_items'] + ($totalQty - 3) * $quote['additional_items']; } break; } // 跳过理论金额为0的异常情况 if ($theoreticalAmount == 0) { Log::warning("京东仓储费计算失败: {$data['document_number']}, 单据类型: {$docType}"); continue; } // 计算费用差额: 结算金额累加 - 理论金额 $balance = $settlementAmount - $theoreticalAmount; $updateData[] = [ //单据编号 'document_number' => $data['document_number'], //单据类型 'document_type' => $docType, //总数量 'total_quantity' => $totalQty, //结算总金额 'total_settlement_amount' => $settlementAmount, //理论金额 'theoretical_amount' => $theoreticalAmount, //差异 'balance' => $balance, //所属年月 'yearMonth' => $yearMonth ]; } // 8. $updateData为最后要插入结果表的数据 批量更新数据库(支持插入和更新) if (!empty($updateData)) { $this->batchUpsert($updateData); $updateCount += count($updateData); } // 9. 内存管理(释放不再使用变量unset($items, $groupedData, $updateData); // 10. 定期执行垃圾回收 if ($batchCount % $gcInterval === 0) { gc_collect_cycles(); } // 11. 定期重连数据库(避免长连接超时) if ($batchCount % $reconnectInterval === 0) { $this->reconnectDatabase(); Log::info("京东仓储服务费用核对已处理 {$updateCount} 条,进行数据库重连"); } // 12. 输出进度日志(每10批次记录一次) if ($batchCount % 10 === 0) { $memUsage = round((memory_get_usage() - $startMemory) / 1024 / 1024, 2); $timeElapsed = round(microtime(true) - $startTime, 2); Log::info("处理进度: {$updateCount}条, 内存占用: {$memUsage}MB, 耗时: {$timeElapsed}秒"); } }); }catch (\Throwable $e) { Log::error("京东仓储费核对系统运行异常: {$e->getMessage()}"); $status = false; } finally { Db::close(); // 最终关闭数据库连接 } // 13. 生成最终统计日志 $peakMemory = round(memory_get_peak_usage() / 1024 / 1024, 2); $totalTime = round(microtime(true) - $startTime, 2); Log::info("京东仓储费核对完成: {$yearMonth}, 处理单据: {$updateCount}条, 峰值内存: {$peakMemory}MB, 总耗时: {$totalTime}秒"); return $status; } // 数据库重连方法,用于长时间运行的任务,避免连接超时 private function reconnectDatabase() { try { $connection = \think\facade\Db::connect(); $connection->close(); // 关闭当前连接 $connection->connect(); // 重新建立连接 } catch (\Exception $e) { // 记录重连失败日志,但不中断程序执行 Log::error('【菜鸟退货入仓费用核对数据库重连失败】' . $e->getMessage()); } } // 获取月份时间范围(返回包含开始和结束时间的数组) private function getMonthTimeRange(string $yearMonth): ?array { if (!preg_match('/^\d{4}-\d{2}$/', $yearMonth)) { return null; } $startTime = date('Y-m-01 00:00:00', strtotime($yearMonth)); $endTime = date('Y-m-t 23:59:59', strtotime($yearMonth)); return ['startTime' => $startTime, 'endTime' => $endTime]; } // 批量插入或更新数据(使用INSERT ON DUPLICATE KEY UPDATE语法) private function batchUpsert(array $data): void { if (empty($data)) return; // 按1000条数据分块处理,避免SQL语句过长 // TODO:根据自己服务器性能适度调整大小 反复测试找到最合适的值即可 $chunks = array_chunk($data, 1000); foreach ($chunks as $chunk) { $values = []; $params = []; // 构建SQL语句的VALUES部分 foreach ($chunk as $row) { $values[] = "(?, ?, ?, ?, ?, ?, ?)"; $params[] = $row['document_number']; $params[] = $row['document_type']; $params[] = $row['total_quantity']; $params[] = $row['total_settlement_amount']; $params[] = $row['theoretical_amount']; $params[] = $row['balance']; $params[] = $row['yearMonth']; } // 构建完整的INSERT ON DUPLICATE KEY UPDATE语句 // 使用了 MySQL 的 INSERT ... ON DUPLICATE KEY UPDATE 语法。这个语法允许我们尝试插入一行,如果该行已经存在(根据唯一索引或主键判断),则改为执行更新操作 // 务必创建la_storage_service_yes 表的唯一键索引:ALTER TABLE `la_storage_service_yes` ADD UNIQUE KEY `idx_document_number` (`document_number`); // 否则ON DUPLICATE KEY UPDATE语法不生效!!! $sql = "INSERT INTO la_storage_service_yes (document_number, document_type, total_quantity, total_settlement_amount, theoretical_amount, balance, yearMonth) VALUES " . implode(',', $values) . " ON DUPLICATE KEY UPDATE document_type = VALUES(document_type), total_quantity = VALUES(total_quantity), total_settlement_amount = VALUES(total_settlement_amount), theoretical_amount = VALUES(theoretical_amount), balance = VALUES(balance), yearMonth = VALUES(yearMonth)"; try { Db::execute($sql, $params); } catch (\Exception $e) { Log::error("京东仓储费批量更新失败: {$e->getMessage()}\nSQL语句: {$sql}"); throw $e; } } } } 就发现2000条数据最后就只读取了500条进行了处理 如果像你说的一样不累加岂不是修改了我的原有逻辑?
07-08
<?php namespace app\common\service\wareHousFee\jingdong\wareHousingFees; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesItemizationModel; use app\common\model\wareHousFee\jingdong\wareHousingFees\WareHousingFeesQuoteModel; use think\facade\Db; use think\facade\Log; use think\db\exception\DataNotFoundException; use think\db\exception\DbException; use think\db\exception\ModelNotFoundException; class WareHousingFeeService { // 存储内存表名称 protected $memoryTableName = ''; public function __construct() {} /** * @notes 京东仓储服务费核对逻辑(内存表优化版) * @param string $yearMonth * @return bool * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author 胡军 * @date 2025/06/27 */ public function wareHousingFeeVerifyDo(string $yearMonth): bool { // 1. 获取月份时间范围 $monthTimeRange = $this->getMonthTimeRange($yearMonth); if (!$monthTimeRange) { Log::error("无效的月份格式: {$yearMonth}"); return false; } // 2. 预加载报价数据 $quoteList = WareHousingFeesQuoteModel::where('service_type', 'IN', ['出库单', '退供单', '退货单']) ->column('first_three_items,additional_items', 'service_type'); if (empty($quoteList)) { Log::warning("京东仓储服务费报价表为空,月份: {$yearMonth}"); return false; } // 3. 配置参数(从环境变量获取或使用默认值) $batchSize = 500; // 批次大小即每次读取的数据条数 $reconnectInterval = 200; // 每10万条重新连接一次数据库(200批次=10万条) $gcInterval = 20; // 垃圾回收间隔 $updateCount = 0; // 处理计数 $batchCount = 0; // 批次计数 $status = true; // 整体状态 // 性能监控变量 $startTime = microtime(true); try { // 4. 创建唯一命名的内存表 $this->memoryTableName = 'mem_warehouse_summary_' . uniqid(); $this->createMemoryTable($this->memoryTableName); //Log::info("创建内存表 {$this->memoryTableName} 成功"); // 5. 创建基础查询 $query = WareHousingFeesItemizationModel::whereBetween('business_time', [ $monthTimeRange['startTime'], $monthTimeRange['endTime'] ]); // 6. 分批次处理数据(只做分组统计,不计算最终结果) $query->chunk($batchSize, function($items) use ( &$batchCount, $reconnectInterval, $gcInterval ) { $batchCount++; // 7. 分组统计(按单据号和单据类型分组) $groupedData = []; foreach ($items as $item) { $key = $item->document_number . '|' . $item->document_type; if (!isset($groupedData[$key])) { $groupedData[$key] = [ 'document_number' => $item->document_number, 'document_type' => $item->document_type, 'total_quantity' => 0, 'total_settlement_amount' => 0 ]; } $groupedData[$key]['total_quantity'] += $item->quantity; $groupedData[$key]['total_settlement_amount'] += $item->settlement_amount; } // 8. 将当前批次的分组结果累加到内存表 $this->accumulateToMemoryTable($groupedData); // 9. 内存管理(释放不再使用变量unset($items, $groupedData); // 10. 定期执行垃圾回收 每10万条执行一次垃圾回收 if ($batchCount % $gcInterval === 0) { gc_collect_cycles(); } // 11. 定期重连数据库(避免长连接超时) if ($batchCount % $reconnectInterval === 0) { $this->reconnectDatabase(); Log::info("京东仓储服务费用核对已处理 {$batchCount} 批次,进行数据库重连"); } }); // 12. 从内存表获取完整的分组数据 // TODO:此处有内存溢出的风险 如果100万条数据都存在内存中,可能会导致内存溢出,严重影响性能甚至崩溃!待优化... $fullGroupedData = Db::table($this->memoryTableName)->select(); // 13. 计算理论金额和差额 $updateData = []; foreach ($fullGroupedData as $data) { $docType = $data['document_type']; $totalQty = $data['total_quantity']; $settlementAmount = $data['total_settlement_amount']; $theoreticalAmount = 0; switch ($docType) { case '出库单': if (isset($quoteList['出库单'])) { $quote = $quoteList['出库单']; $theoreticalAmount = ($totalQty <= 3) ? $quote['first_three_items'] : $quote['first_three_items'] + ($totalQty - 3) * $quote['additional_items']; } break; case '退供单': if (isset($quoteList['退供单'])) { $quote = $quoteList['退供单']; $theoreticalAmount = $quote['first_three_items'] * $totalQty; } break; case '退货单': if (isset($quoteList['退货单'])) { $quote = $quoteList['退货单']; $theoreticalAmount = ($totalQty <= 3) ? $quote['first_three_items'] : $quote['first_three_items'] + ($totalQty - 3) * $quote['additional_items']; } break; } if ($theoreticalAmount == 0) { Log::warning("京东仓储费计算失败: {$data['document_number']}, 单据类型: {$docType}"); continue; } $balance = $settlementAmount - $theoreticalAmount; $updateData[] = [ 'document_number' => $data['document_number'], 'document_type' => $docType, 'total_quantity' => $totalQty, 'total_settlement_amount' => $settlementAmount, 'theoretical_amount' => $theoreticalAmount, 'balance' => $balance, 'yearMonth' => $yearMonth ]; $updateCount++; } // 14. 批量更新到结果表 if (!empty($updateData)) { $this->batchUpsert($updateData); Log::info("成功更新 {$updateCount} 条仓储费核对结果"); } } catch (\Throwable $e) { Log::error("京东仓储费核对系统运行异常: {$e->getMessage()}"); $status = false; } finally { // 15. 确保删除内存表(即使处理失败) if ($this->memoryTableName) { $this->dropMemoryTable($this->memoryTableName); } Db::close(); // 最终关闭数据库连接 } // 16. 生成最终统计日志 $peakMemory = round(memory_get_peak_usage() / 1024 / 1024, 2); $totalTime = round(microtime(true) - $startTime, 2); Log::info("京东仓储费核对完成: {$yearMonth}, 处理单据: {$updateCount}条, 峰值内存: {$peakMemory}MB, 总耗时: {$totalTime}秒"); return $status; } /** * 创建内存表用于存储中间结果 * @param string $tableName 内存表名称 */ private function createMemoryTable(string $tableName) { $sql = "CREATE TABLE IF NOT EXISTS `{$tableName}` ( document_number VARCHAR(50) NOT NULL, document_type VARCHAR(20) NOT NULL, total_quantity DECIMAL(12,2) NOT NULL DEFAULT 0, total_settlement_amount DECIMAL(12,2) NOT NULL DEFAULT 0, PRIMARY KEY (document_number, document_type) ) ENGINE=MEMORY"; // 使用内存引擎提高性能 try { Db::execute($sql); } catch (\Exception $e) { Log::error("创建内存表失败: {$e->getMessage()}"); throw new \Exception("无法创建内存表: {$tableName}"); } } /** * 将分组结果累加到内存表 * @param array $groupedData 分组后的数据 */ private function accumulateToMemoryTable(array $groupedData) { if (empty($groupedData)) return; // 使用事务确保原子性 Db::startTrans(); try { foreach ($groupedData as $data) { // 使用UPSERT操作(存在则更新,不存在则插入) Db::execute(" INSERT INTO `{$this->memoryTableName}` (document_number, document_type, total_quantity, total_settlement_amount) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE total_quantity = total_quantity + VALUES(total_quantity), total_settlement_amount = total_settlement_amount + VALUES(total_settlement_amount) ", [ $data['document_number'], $data['document_type'], $data['total_quantity'], $data['total_settlement_amount'] ]); } Db::commit(); } catch (\Exception $e) { Db::rollback(); Log::error("内存表数据累加失败: {$e->getMessage()}"); throw $e; } } /** * 删除内存表 * @param string $tableName 要删除的内存表名称 */ private function dropMemoryTable(string $tableName) { try { Db::execute("DROP TABLE IF EXISTS `{$tableName}`"); Log::info("内存表 {$tableName} 已删除"); } catch (\Exception $e) { Log::error("删除内存表失败: {$e->getMessage()}"); } } /** * 数据库重连方法,用于长时间运行的任务,避免连接超时 */ private function reconnectDatabase() { try { $connection = \think\facade\Db::connect(); $connection->close(); // 关闭当前连接 $connection->connect(); // 重新建立连接 } catch (\Exception $e) { Log::error('【京东仓储服务费核对数据库重连失败】' . $e->getMessage()); } } /** * 获取月份时间范围(返回包含开始和结束时间的数组) * @param string $yearMonth 年月字符串(格式:YYYY-MM) * @return array|null */ private function getMonthTimeRange(string $yearMonth): ?array { if (!preg_match('/^\d{4}-\d{2}$/', $yearMonth)) { return null; } $startTime = date('Y-m-01 00:00:00', strtotime($yearMonth)); $endTime = date('Y-m-t 23:59:59', strtotime($yearMonth)); return ['startTime' => $startTime, 'endTime' => $endTime]; } /** * 批量插入或更新数据(使用INSERT ON DUPLICATE KEY UPDATE语法) * @param array $data 要更新的数据 */ private function batchUpsert(array $data): void { if (empty($data)) return; // 按1000条数据分块处理,避免SQL语句过长 $chunks = array_chunk($data, 1000); foreach ($chunks as $chunk) { $values = []; $params = []; // 构建SQL语句的VALUES部分 foreach ($chunk as $row) { $values[] = "(?, ?, ?, ?, ?, ?, ?)"; $params[] = $row['document_number']; $params[] = $row['document_type']; $params[] = $row['total_quantity']; $params[] = $row['total_settlement_amount']; $params[] = $row['theoretical_amount']; $params[] = $row['balance']; $params[] = $row['yearMonth']; } // 构建完整的INSERT ON DUPLICATE KEY UPDATE语句 $sql = "INSERT INTO la_storage_service_yes (document_number, document_type, total_quantity, total_settlement_amount, theoretical_amount, balance, yearMonth) VALUES " . implode(',', $values) . " ON DUPLICATE KEY UPDATE document_type = VALUES(document_type), total_quantity = VALUES(total_quantity), total_settlement_amount = VALUES(total_settlement_amount), theoretical_amount = VALUES(theoretical_amount), balance = VALUES(balance), yearMonth = VALUES(yearMonth)"; try { Db::execute($sql, $params); } catch (\Exception $e) { Log::error("京东仓储费批量更新失败: {$e->getMessage()}\nSQL语句: {$sql}"); throw $e; } } } } 请在我的代码的基础上完善,并且为我提供完善好的代码,不要忘记注释信息
07-08
内容概要:本文围绕直流微电网中带有恒功率负载(CPL)的DC/DC升压转换器的稳定控制问题展开研究,提出了一种复合预设性能控制策略。首先,通过精确反馈线性化技术将非线性不确定的DC转换器系统转化为Brunovsky标准型,然后利用非线性扰动观测器评估负载功率的动态变化和输出电压的调节精度。基于反步设计方法,设计了具有预设性能的复合非线性控制器,确保输出电压跟踪误差始终在预定义误差范围内。文章还对比了多种DC/DC转换器控制技术如脉冲调整技术、反馈线性化、滑模控制(SMC)、主动阻尼法和基于无源性的控制,并分析了它们的优缺点。最后,通过数值仿真验证了所提控制器的有效性和优越性。 适合人群:从事电力电子、自动控制领域研究的学者和工程师,以及对先进控制算法感兴趣的研究生及以上学历人员。 使用场景及目标:①适用于需要精确控制输出电压并处理恒功率负载的应用场景;②旨在实现快速稳定的电压跟踪,同时保证系统的鲁棒性和抗干扰能力;③为DC微电网中的功率转换系统提供兼顾瞬态性能和稳态精度的解决方案。 其他说明:文中不仅提供了详细的理论推导和算法实现,还通过Python代码演示了控制策略的具体实现过程,便于读者理解和实践。此外,文章还讨论了不同控制方法的特点和适用范围,为实际工程项目提供了有价值的参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值