【问题标题】:Casting varchar to date in where query Laravel 5.2在查询 Laravel 5.2 中将 varchar 转换为日期
【发布时间】:2018-07-02 13:22:28
【问题描述】:

我正在尝试从使用日期作为排序列的范围中选择数据集合。但问题是我表中的日期保存为 varchar 字符串。

注意:varchar 字段类型需要保持与某些非 laravel 遗留代码库使用的一样,如果更改为日期类型,我将中断服务。

我试过投射它,但它不起作用。

这是控制器中的代码

        switch ($range) {
        case 'thisWeek':
            $start = Carbon::now()->startOfWeek()->format('d-m-y');
            $end = Carbon::now()->endOfWeek()->format('d-m-Y');     
            break;

        case 'thisMonth':
            $start = Carbon::now()->startOfMonth()->format('d-m-Y');
            $end = Carbon::now()->endOfMonth()->format('d-m-Y');
            // dd($start, $end);
            break;


        case 'last90Days':
            $start = Carbon::now()->format('d-m-Y');
            $end = Carbon::now()->subDays(90)->format('d-m-Y');

            // dd($start, $end);
            break;

        case 'last30Days':
            $start = Carbon::now()->format('d-m-Y');
            $end = Carbon::now()->subDays(30)->format('d-m-Y');
            break;


        case 'year':
            $start = Carbon::now()->format('d-m-Y');
            $end = Carbon::now()->year;
            $end = "31-12-". $end;
            break;

        // case 'all':
        //  $route = $name .".". "index";
        //  return redirect()->Route($route);

        default:
            session()->flash("alert-danger", "no range selected");
            return redirect()->back();
            break;
    }

    if($name=="activitylog"){

        // return $start . ' <br>' . $end;

        $logs = Payment::where("payDate", '<', $start)->where("payDate", ">", $end)->
                        orderBy("payDate", "DESC")->
                        paginate(20);
    }
    else{
        $logs = Payment::where("description", $description[$name])->
                    where("payDate", '=<', $start)->where("payDate", ">=", $end)->
                    orderBy("payDate", "DESC")->
                    paginate(20);   

型号:

<?php

namespace App\Models\Admin;

use Illuminate\Database\Eloquent\Model;

class Payment extends Model
{
    protected $table = "payments";
    public $timestamps = false;
    protected $cast = ["payDate"=> "DATE"];
}

当用户对我希望比较的任何范围提出请求并给出答案时。

数据库配置的图像在上面 和下面的结构

【问题讨论】:

  • 在您创建它的架构中,尝试使用$table-&gt;date('payDate'); 创建日期字段而不是varchar,并在您的模型中使用public $dates = ['payDate'] 作为属性。然后你应该可以只插入 carbon 实例,laravel 会做剩下的事情。
  • 旁注:laravel 5.2 已经快一年没有收到更新了。考虑升级。 endoflife.software/programming-languages/frameworks/laravel
  • @Tschallacka 我无法真正编辑数据库,因为它是一个遗留项目,并且有很多我不想触及的代码的其他方面取决于它。其他方面不是用 Laravel 构建的。所以我只想能够用 laravel 找到解决方法
  • @Loek 我真的希望我能,但我不能。
  • @Thirdwrist 请在您的问题中包含该信息,因为它与 varchar 字段类型需要保留的可能答案非常相关。

标签: php sorting date laravel-5.2


【解决方案1】:

你必须使用mysql的STR_TO_DATE函数。

您要查找的原始 SQL 查询是:

查看实际操作:http://sqlfiddle.com/#!9/a40090/8

select * from `test` where str_to_date(`payDate`, '%d-%m-%Y') > str_to_date('31-12-2007', '%d-%m-%Y');

STR_TO_DATE 告诉 MySQL 日期的格式,这有助于 MySQL 返回正确的日期以进行排序等。

您的 Eloquent 查询将看起来像这样:

 /** put it like this so we don't have to repeat it everywhere where needed **/
 $paydate_raw = DB::raw("STR_TO_DATE(`payDate`, '%d-%m-%Y')");

 /** encoding the raw query. the ? is populated by setBindings() **/
 $start_raw = DB::raw("STR_TO_DATE(?, '%d-%m-%Y')");
 $end_raw = DB::raw("STR_TO_DATE(?, '%d-%m-%Y')");


  $query = Payment::where($paydate_raw, '<', $start_raw)->where($paydate_raw, ">", $end_raw)->
                    orderBy('paydate', "DESC")->
                    setBindings([$start, $end])->
                    paginate(20);
  // debugging output.
  //echo $query->toSql();

请注意,上面的代码只是一个概念,我还没有测试过,但它应该可以工作。还请查看 SQL fiddle 以了解它应该如何以原始方式响应。

【讨论】:

  • 这太棒了!谢谢。让我试试看。再三考虑,我是否需要在查询中防止 SQL 注入?因为它没有任何用户定义的参数。当用户在 switch 语句中选择一个选项时,所有日期都由我定义。
  • 经验法则,总是使用准备好的语句。有了这段代码,你永远不会知道两年后会发生什么。
猜你喜欢
  • 1970-01-01
  • 2015-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-10
  • 2019-12-20
  • 1970-01-01
相关资源
最近更新 更多