M'Baku
M'Baku

Reputation: 320

Casting varchar to date in where query Laravel 5.2

I am trying to pick a collection of data from a range using the date as the sorting column. But the problem is that the date in my table is saved as a varchar string.

NOTE: The varchar field type needs to stay as it used by some non laravel, legacy codebase, and I will disrupt service if altered to date type.

I have tried casting it but it doesn't work.

This is the code in the controller

        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);   

the model:

<?php

namespace App\Models\Admin;

use Illuminate\Database\Eloquent\Model;

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

When the user makes a request for any of the ranges I wish to compare and give an answer.

dates example

the image for the database config is above and the structure below table structure

Upvotes: 1

Views: 4266

Answers (1)

Tschallacka
Tschallacka

Reputation: 28722

You will have to use the STR_TO_DATE function of mysql.

The raw SQL query you're looking for is:

See it in action: 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');

With STR_TO_DATE you tell MySQL in what format the date is formatted which helps MySQL to give back the proper date for sorting and such.

Your Eloquent query will then come to look somewhat like this:

 /** 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();

Note the above code is just a concept, I haven't tested it out, but it should work. Take a look also at the SQL fiddle to see how it should respond in raw.

Upvotes: 3

Related Questions