You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Laravel单表单多输入处理:考勤打卡字段存储问题求助

解决Laravel考勤表单的两个核心问题

嘿,作为Laravel新手碰到这种考勤标记的场景很正常,我来帮你一步步搞定这两个问题:只存储对应标记的字段、标记后按钮替换为勾选并禁用至次日。


问题1:仅存储点击按钮对应的字段,其余为null

当前你的所有字段都在同一个<form>里,点击任意按钮都会提交所有隐藏输入框的值,导致所有字段都被存入数据库。我们可以通过按钮标记动作来解决,同时优化记录逻辑(避免重复创建每日记录):

步骤1:修改视图,给按钮添加动作标记

去掉冗余的隐藏输入框,给每个按钮添加name="action"和对应的值,让控制器能识别点击的是哪个标记按钮:

<div class="card" style="max-width: 600px; margin:auto; margin-bottom:50px;margin-top:40px;">
    <div class="card-header" style="text-align:center"> 
        Today: {{ \Carbon\Carbon::now()->format('d-m-Y') }}
    </div>
    <form action="{{ route('timesheet.store') }}" method="POST">
        @csrf
        <div class="card-body">
            <ul class="list-group">
                <li class="list-group-item">
                    <label>Day start</label>
                    <span style="float:right">
                        <button type="submit" class="btn btn-success btn-sm" name="action" value="in_time">Mark</button>
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Break-out</label>
                    <span style="float:right">
                        <button type="submit" class="btn btn-success btn-sm" name="action" value="break_out">Mark</button>
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Break-in</label>
                    <span style="float:right">
                        <button type="submit" class="btn btn-success btn-sm" name="action" value="break_in">Mark</button>
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Day end</label>
                    <span style="float:right">
                        <button type="submit" class="btn btn-success btn-sm" name="action" value="out_time">Mark</button>
                    </span>
                </li>
            </ul>
        </div>
    </form>
</div>

这里直接用服务器端生成时间,避免客户端篡改时间,更安全可靠。

步骤2:修改控制器,只处理对应动作的字段

firstOrCreate确保用户每天只有一条考勤记录,避免重复创建:

use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;

public function store(Request $request) {
    // 获取或创建当前用户今日的考勤记录
    $today = Carbon::today()->toDateString();
    $timesheet = Timesheet::firstOrCreate(
        ['user_id' => Auth::user()->id, 'date' => $today], // 假设表中有date字段存储日期
        ['user_id' => Auth::user()->id]
    );

    // 根据点击的按钮,设置对应字段的时间
    $action = $request->input('action');
    if (in_array($action, ['in_time', 'break_out', 'break_in', 'out_time'])) {
        $timesheet->$action = Carbon::now();
        $timesheet->save();
    }

    return redirect()->route('timesheet.create')
        ->with('success', 'Attendance marked successfully.');
}

如果你的表没有date字段,可将查询条件改为:

['user_id' => Auth::user()->id],
function ($query) {
    $query->whereDate('created_at', Carbon::today());
}

问题2:标记成功后替换为勾选图标,禁用至次日零点

我们需要在视图中判断当前用户今日的考勤记录哪些字段已填充,动态渲染按钮或勾选图标:

步骤1:在Create方法中传递今日考勤记录

TimesheetControllercreate方法中,获取用户今日的考勤记录:

public function create() {
    $todayTimesheet = Timesheet::where('user_id', Auth::user()->id)
        ->whereDate('created_at', Carbon::today())
        ->first();

    return view('timesheet.create', compact('todayTimesheet'));
}

步骤2:修改视图,动态渲染按钮/勾选图标

@if判断字段是否存在值,显示对应状态(这里用Bootstrap图标,也可以用文字代替):

<div class="card" style="max-width: 600px; margin:auto; margin-bottom:50px;margin-top:40px;">
    <div class="card-header" style="text-align:center"> 
        Today: {{ Carbon::now()->format('d-m-Y') }}
    </div>
    <form action="{{ route('timesheet.store') }}" method="POST">
        @csrf
        <div class="card-body">
            <ul class="list-group">
                <li class="list-group-item">
                    <label>Day start</label>
                    <span style="float:right">
                        @if($todayTimesheet && $todayTimesheet->in_time)
                            <span style="color: green; font-size: 1.2rem;">
                                <i class="bi bi-check-circle-fill"></i>
                            </span>
                        @else
                            <button type="submit" class="btn btn-success btn-sm" name="action" value="in_time">Mark</button>
                        @endif
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Break-out</label>
                    <span style="float:right">
                        @if($todayTimesheet && $todayTimesheet->break_out)
                            <span style="color: green; font-size: 1.2rem;">
                                <i class="bi bi-check-circle-fill"></i>
                            </span>
                        @else
                            <button type="submit" class="btn btn-success btn-sm" name="action" value="break_out">Mark</button>
                        @endif
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Break-in</label>
                    <span style="float:right">
                        @if($todayTimesheet && $todayTimesheet->break_in)
                            <span style="color: green; font-size: 1.2rem;">
                                <i class="bi bi-check-circle-fill"></i>
                            </span>
                        @else
                            <button type="submit" class="btn btn-success btn-sm" name="action" value="break_in">Mark</button>
                        @endif
                    </span>
                </li>
                <li class="list-group-item">
                    <label>Day end</label>
                    <span style="float:right">
                        @if($todayTimesheet && $todayTimesheet->out_time)
                            <span style="color: green; font-size: 1.2rem;">
                                <i class="bi bi-check-circle-fill"></i>
                            </span>
                        @else
                            <button type="submit" class="btn btn-success btn-sm" name="action" value="out_time">Mark</button>
                        @endif
                    </span>
                </li>
            </ul>
        </div>
    </form>
</div>

这样标记后页面会显示勾选图标,次日零点后Carbon::today()切换到新日期,用户的今日记录为空,按钮会自动重新显示。


额外优化建议

  • Timesheet模型添加$fillable属性,确保字段可以批量赋值:
    protected $fillable = ['user_id', 'in_time', 'out_time', 'break_out', 'break_in', 'date'];
    
  • 建议给表添加date类型字段,方便快速查询每日考勤记录。

内容的提问来源于stack exchange,提问作者Pawan

火山引擎 最新活动