You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:50:16