转换日期时间不适用于 select 原始查询生成器,但 eloquent 可以
Cast datetime not working on select raw query builder but eloquent is ok
我正在使用 laravel 5.7 并且有一个这样的模型:
class Task extends Model
{
use SoftDeletes;
protected $table = 'com_tasks';
///...
//protected $dates = ['deleted_at'];
protected $casts = [
'start_date' => 'datetime:Y/m/d H:i:s',
'due_date' => 'datetime:Y/m/d H:i:s',
];
/**
* get list data
*
* @param $params
* @return array list com_tasks
*/
public function list($params=[])
{
$result = $this->select(
'com_tasks.id',
'com_tasks.name',
'com_tasks.done',
'com_task_status.id AS status_id',
'com_task_status.name AS status_name',
'com_task_status.color AS status_color',
'com_projects.name AS project_name',
'com_projects.name AS assignee_name'
)
->selectRaw(DB::raw('
DATE_FORMAT(com_tasks.start_date, "%Y/%m/%d %H:%i:%s") as start_date,
DATE_FORMAT(com_tasks.due_date, "%Y/%m/%d %H:%i:%s") as due_date
'))
->leftJoin('com_task_status', 'com_tasks.status_id', 'com_task_status.id')
->leftJoin('com_projects', 'com_tasks.project_id', 'com_projects.id');
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $result->orderBy('id', 'DESC')->paginate($per_page);
}
///...
}
当我将这个模型绑定到路由器时,它工作正常但是当我调用:(new Task)->list($conditions);我得到一个错误:
{"status":false,"message":"Unexpected data found.
Unexpected data found.","class":"InvalidArgumentException","file":"D:\Projects\backend\vendor\
esbot\carbon\src\Carbon\Carbon.php","line":909,"code":0}
但是当我注释 $casts 变量时,它起作用了。为什么会这样?
P/S:当我尝试将 'start_date' 放入 $dates 时,我遇到了同样的错误。
好吧,首先 list()
方法应该是控制器的一部分,并且您应该使用 Laravel 本地关系处理程序...看看 official documentation.
无论如何,问题是 $cast
变量试图将您的查询结果转换为 Carbon
object,然后将结果格式化为 Y/m/d H:i:s
格式。但输入的不是时间戳,它只是一个字符串(因为您在查询中是 运行 DATE_FORMAT(com_tasks.start_date, "%Y/%m/%d %H:%i:%s") as start_date
)。这就是抛出异常的原因。
如果您想使用 $cast
或 $dates
属性,您应该简单地恢复 start_date
和 due_date
列。您的代码将变为:
$result = $this->select(
'com_tasks.id',
'com_tasks.name',
'com_tasks.done',
'com_task_status.id AS status_id',
'com_task_status.name AS status_name',
'com_task_status.color AS status_color',
'com_projects.name AS project_name',
'com_projects.name AS assignee_name',
'com_tasks.start_date AS start_date',
'com_tasks.due_date AS due_date',
)
->leftJoin('com_task_status', 'com_tasks.status_id', 'com_task_status.id')
->leftJoin('com_projects', 'com_tasks.project_id', 'com_projects.id');
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $result->orderBy('id', 'DESC')->paginate($per_page);
正如我一开始写的那样,最好的解决方案应该是:
class Task extends Model
{
use SoftDeletes;
protected $table = 'com_tasks';
protected $dates = ['deleted_at', 'start_date', 'due_date'];
/**
* get list data
*
* @param $params
* @return array list com_tasks
*/
public function list($params=[])
{
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $this->with(['taskStatus', 'project'])->orderBy('id', 'DESC')->paginate($per_page);
}
public function taskStatus()
{
return $this->belongsTo(TaskStatus::class);
}
public function project()
{
return $this->belongsTo(Project::class);
}
}
并且在您的控制器/blade 视图/任何调用格式方法的地方,因为 deleted_at
、start_date
和 due_date
属性被实例化为 Carbon
objects.
// ... your code
$model->start_date->format('Y/m/d H:i:s');
// ... your blade view
{{ $model->start_date->format('Y/m/d H:i:s'); }}
我正在使用 laravel 5.7 并且有一个这样的模型:
class Task extends Model
{
use SoftDeletes;
protected $table = 'com_tasks';
///...
//protected $dates = ['deleted_at'];
protected $casts = [
'start_date' => 'datetime:Y/m/d H:i:s',
'due_date' => 'datetime:Y/m/d H:i:s',
];
/**
* get list data
*
* @param $params
* @return array list com_tasks
*/
public function list($params=[])
{
$result = $this->select(
'com_tasks.id',
'com_tasks.name',
'com_tasks.done',
'com_task_status.id AS status_id',
'com_task_status.name AS status_name',
'com_task_status.color AS status_color',
'com_projects.name AS project_name',
'com_projects.name AS assignee_name'
)
->selectRaw(DB::raw('
DATE_FORMAT(com_tasks.start_date, "%Y/%m/%d %H:%i:%s") as start_date,
DATE_FORMAT(com_tasks.due_date, "%Y/%m/%d %H:%i:%s") as due_date
'))
->leftJoin('com_task_status', 'com_tasks.status_id', 'com_task_status.id')
->leftJoin('com_projects', 'com_tasks.project_id', 'com_projects.id');
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $result->orderBy('id', 'DESC')->paginate($per_page);
}
///...
}
当我将这个模型绑定到路由器时,它工作正常但是当我调用:(new Task)->list($conditions);我得到一个错误:
{"status":false,"message":"Unexpected data found.
Unexpected data found.","class":"InvalidArgumentException","file":"D:\Projects\backend\vendor\
esbot\carbon\src\Carbon\Carbon.php","line":909,"code":0}
但是当我注释 $casts 变量时,它起作用了。为什么会这样?
P/S:当我尝试将 'start_date' 放入 $dates 时,我遇到了同样的错误。
好吧,首先 list()
方法应该是控制器的一部分,并且您应该使用 Laravel 本地关系处理程序...看看 official documentation.
无论如何,问题是 $cast
变量试图将您的查询结果转换为 Carbon
object,然后将结果格式化为 Y/m/d H:i:s
格式。但输入的不是时间戳,它只是一个字符串(因为您在查询中是 运行 DATE_FORMAT(com_tasks.start_date, "%Y/%m/%d %H:%i:%s") as start_date
)。这就是抛出异常的原因。
如果您想使用 $cast
或 $dates
属性,您应该简单地恢复 start_date
和 due_date
列。您的代码将变为:
$result = $this->select(
'com_tasks.id',
'com_tasks.name',
'com_tasks.done',
'com_task_status.id AS status_id',
'com_task_status.name AS status_name',
'com_task_status.color AS status_color',
'com_projects.name AS project_name',
'com_projects.name AS assignee_name',
'com_tasks.start_date AS start_date',
'com_tasks.due_date AS due_date',
)
->leftJoin('com_task_status', 'com_tasks.status_id', 'com_task_status.id')
->leftJoin('com_projects', 'com_tasks.project_id', 'com_projects.id');
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $result->orderBy('id', 'DESC')->paginate($per_page);
正如我一开始写的那样,最好的解决方案应该是:
class Task extends Model
{
use SoftDeletes;
protected $table = 'com_tasks';
protected $dates = ['deleted_at', 'start_date', 'due_date'];
/**
* get list data
*
* @param $params
* @return array list com_tasks
*/
public function list($params=[])
{
$per_page = $params['per_page'] ?? config('pagination.per_page');
return $this->with(['taskStatus', 'project'])->orderBy('id', 'DESC')->paginate($per_page);
}
public function taskStatus()
{
return $this->belongsTo(TaskStatus::class);
}
public function project()
{
return $this->belongsTo(Project::class);
}
}
并且在您的控制器/blade 视图/任何调用格式方法的地方,因为 deleted_at
、start_date
和 due_date
属性被实例化为 Carbon
objects.
// ... your code
$model->start_date->format('Y/m/d H:i:s');
// ... your blade view
{{ $model->start_date->format('Y/m/d H:i:s'); }}