转换日期时间不适用于 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_datedue_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_atstart_datedue_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'); }}