解决Laravel中Jalali转Georgian日期后控制器获原日期的问题
问题根源
模型的setTaskDateAttribute是Eloquent赋值修改器,它仅在给模型的TaskDate属性赋值(比如$task->TaskDate = $value或调用Task::create($attributes))时触发,自动转换值并存入数据库字段。它不会修改请求对象($request)里的原始数据,所以控制器中dd($request->TaskDate)看到原始Jalali日期是正常现象,但你存不进转换后日期的原因是:
- 控制器里的
dd($request->TaskDate)直接终止了程序,后续模型写入逻辑根本没执行; - 你的
TaskService的create方法可能绕过了Eloquent模型,直接用DB门面操作数据库,导致修改器未被触发。
解决方案
1. 移除控制器中的终止代码,让流程执行到模型写入
控制器里的dd会打断程序,删掉它才能触发模型的修改器逻辑:
public function store(taskRequestStore $request,TaskService $service) { // 移除这行终止代码 // dd($request->TaskDate); // 建议用only替代all,更精准获取所需字段 $attributes = $request->only(['office_id','TaskDate','Type','Priority_id']); // 变量名修正为$task,和业务逻辑匹配 $task = $service->create($attributes); }
2. 确保Service的create方法正确使用Eloquent模型
检查TaskService的create方法,必须通过Eloquent模型创建数据,才能触发修改器:
// TaskService.php 正确实现 public function create(array $attributes) { // 调用模型的create方法,自动触发setTaskDateAttribute return \App\Models\Task::create($attributes); }
如果是以下这种直接操作数据库的写法,会绕过模型修改器,必须改掉:
// 错误示例:避免直接用DB门面插入 public function create(array $attributes) { return DB::table('tasks')->insert($attributes); }
3. (可选)在请求类中提前转换日期
如果需要在控制器中直接拿到转换后的日期,可以在请求类的prepareForValidation方法中处理:
// app/Http/Requests/taskRequestStore.php public function prepareForValidation() { $rawDate = $this->input('TaskDate'); $convertedDate = CalendarUtils::convertNumbers($rawDate, true); $convertedDate = CalendarUtils::createCarbonFromFormat('Y-m-d', $convertedDate)->format('Y-m-d'); // 将转换后的数据合并到请求中 $this->merge(['TaskDate' => $convertedDate]); }
这种方式和模型修改器二选一即可,推荐用模型修改器,因为转换逻辑放在模型里更符合职责分离原则。
额外注意
- 模型里的
dd($this->TaskDate)必须删掉,否则每次赋值都会终止程序,无法完成写入; - 检查变量名一致性:控制器中的
$office应该改为$task,避免业务逻辑混淆。
内容的提问来源于stack exchange,提问作者mahdi.gh
相关产品推荐
相关产品推荐

