Laravel 5.6中基于年份与下拉选项的自动编号实现咨询
嘿,这个需求我之前在Laravel项目里处理过类似的,在5.6版本里实现起来挺清晰的,咱们一步步拆解来做:
1. 先搞定数据库表设计
首先你需要一张表来存储这些带编号的记录,比如命名为documents,至少需要这几个核心字段:
id:主键自增type:用来存储选择的类型(比如NK/W或NK/S)serial_number:存储生成的完整编号created_at:时间戳(用来提取年份,判断是否需要重置序号)
你可以用迁移命令创建这张表:
// 生成迁移文件 php artisan make:migration create_documents_table // 在迁移文件里写字段 public function up() { Schema::create('documents', function (Blueprint $table) { $table->increments('id'); $table->string('type'); $table->string('serial_number')->unique(); // 编号唯一,避免重复 $table->timestamps(); }); }
2. 模型里实现编号生成的核心逻辑
在对应的模型(比如Document.php)里,写一个静态方法来自动计算下一个编号,核心思路是:根据选择的类型+当前年份,统计已有记录数,加1后格式化为三位数字,再拼接成完整编号。
// app/Document.php namespace App; use Illuminate\Database\Eloquent\Model; class Document extends Model { protected $fillable = ['type', 'serial_number']; public static function getNextSerialNumber($selectedType) { $currentYear = date('Y'); // 或者用Carbon::now()->year,记得引入Carbon // 关键:统计同类型、同年份的记录总数 $recordCount = self::where('type', $selectedType) ->whereYear('created_at', $currentYear) ->count(); // 把序号格式化为三位带前导零的数字 $nextSeq = str_pad($recordCount + 1, 3, '0', STR_PAD_LEFT); // 拼接成最终编号 return "{$nextSeq}/{$selectedType}/{$currentYear}"; } }
3. 控制器处理表单提交
当用户选择类型提交表单时,调用上面的方法生成编号,然后保存到数据库:
// app/Http/Controllers/DocumentController.php namespace App\Http\Controllers; use App\Document; use Illuminate\Http\Request; class DocumentController extends Controller { public function store(Request $request) { // 验证提交的类型是否合法 $request->validate([ 'type' => 'required|in:NK/W,NK/S', // 其他表单字段的验证规则 ]); // 生成下一个编号 $newSerialNumber = Document::getNextSerialNumber($request->type); // 保存记录 Document::create([ 'type' => $request->type, 'serial_number' => $newSerialNumber, // 其他字段赋值 ]); return redirect()->back()->with('success', "记录创建成功!编号:{$newSerialNumber}"); } }
4. 视图里的下拉列表
按照你的需求做下拉选择框,样式可以根据附图调整,这里给个基础的Blade模板示例:
<!-- resources/views/documents/create.blade.php --> <form method="POST" action="{{ route('documents.store') }}"> @csrf <div class="form-group"> <label>选择类型</label> <select name="type" class="form-control"> <option value="NK/W">NK/W</option> <option value="NK/S">NK/S</option> </select> </div> <!-- 其他表单元素 --> <button type="submit" class="btn btn-primary">提交</button> </form>
重要补充:处理并发重复问题
如果有多个用户同时提交,可能会出现编号重复的情况,这时候可以用数据库事务+行锁来避免:
修改模型里的getNextSerialNumber方法,加上事务和锁:
public static function getNextSerialNumber($selectedType) { $currentYear = date('Y'); return \DB::transaction(function () use ($selectedType, $currentYear) { // 使用lockForUpdate锁定查询的行,避免并发修改 $recordCount = self::where('type', $selectedType) ->whereYear('created_at', $currentYear) ->lockForUpdate() ->count(); $nextSeq = str_pad($recordCount + 1, 3, '0', STR_PAD_LEFT); return "{$nextSeq}/{$selectedType}/{$currentYear}"; }); }
这样就能保证同一时间只有一个请求能生成编号,避免重复。
内容的提问来源于stack exchange,提问作者Ihsan
相关产品推荐
相关产品推荐

