Laravel 7 如何生成符合[编码-日期-序号]格式的自动交易编码
Laravel 7 生成指定格式唯一交易编码实现方案
核心逻辑为获取当日已生成的最大序号,自增后拼接前缀、日期、补零序号即可,配合事务和唯一索引兜底避免重复。
第一步:数据库适配
- 给交易表增加交易编码字段并设置唯一索引,防止重复编码入库,迁移代码如下:
Schema::table('transactions', function (Blueprint $table) { $table->string('transaction_no', 32)->unique(); });
- 前缀如果需要灵活调整,可以在
config/app.php中添加配置项,示例使用固定前缀PSN。
第二步:封装生成逻辑
建议将生成方法封装到对应的交易模型中,示例如下:
<?php namespace App; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\DB; class Transaction extends Model { // 日期格式,示例dmY对应输出22102021(2021年10月22日),需要年月日格式改为Ymd即可 const DATE_FORMAT = 'dmY'; // 序号补零长度,3位对应001、002,按需调整 const SERIAL_LENGTH = 3; // 交易编码前缀 const PREFIX = 'PSN'; public static function generateTransactionNo() { // 开启事务加锁避免并发场景下生成重复编码 return DB::transaction(function () { $today = now()->format(self::DATE_FORMAT); // 查找当日最新的交易记录,加行锁防止并发读取同一份最大值 $latest = self::where('transaction_no', 'like', self::PREFIX . "-{$today}-%") ->orderBy('id', 'desc') ->lockForUpdate() ->first(); // 计算新序号 if ($latest) { $lastSerial = (int)substr($latest->transaction_no, strrpos($latest->transaction_no, '-') + 1); $newSerial = str_pad($lastSerial + 1, self::SERIAL_LENGTH, '0', STR_PAD_LEFT); } else { $newSerial = str_pad(1, self::SERIAL_LENGTH, '0', STR_PAD_LEFT); } // 拼接编码,不需要日期和序号之间的分隔符就删掉第二个"-",即可生成PSN-22102021001格式 return self::PREFIX . "-{$today}-{$newSerial}"; }); } }
第三步:调用方法
创建交易记录时直接调用方法赋值即可:
$transaction = new Transaction(); $transaction->transaction_no = Transaction::generateTransactionNo(); // 其他业务字段赋值 $transaction->save();
高并发场景优化
如果业务并发量较高,可以提前预生成一批交易编码存入单独的编码池表,使用时直接取走标记为已用,性能优于实时生成。
内容的提问来源于stack exchange,提问作者user15798630
相关产品推荐
相关产品推荐

