mercredi 16 mai 2018

Laravel: How to use querybuilder with select-raw?

I found at https://stackoverflow.com/a/44002632/2311074 this code-snippet:

public static function scopeGetByDistance($query,$lat, $lng, $distance)
{
  $results = DB::select(DB::raw('SELECT id, ( 3959 * acos( cos( radians(' . $lat . ') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(' . $lng . ') ) + sin( radians(' . $lat .') ) * sin( radians(lat) ) ) ) AS distance FROM articles HAVING distance < ' . $distance . ' ORDER BY distance') );

    if(!empty($results)) {

        $ids = [];

        //Extract the id's
        foreach($results as $q) {
           array_push($ids, $q->id);
        }

        return $query->whereIn('id',$ids);

    }

    return $query;

 }

And I was wondering why one could not simply reduce this to

public static function scopeGetByDistanceClean($query,$lat, $lng, $distance)
{
   return $query->select(DB::raw('SELECT id, ( 3959 * acos( cos( radians(' . $lat . ') ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(' . $lng . ') ) + sin( radians(' . $lat .') ) * sin( radians(lat) ) ) ) AS distance FROM articles HAVING distance < ' . $distance . ' ORDER BY distance') );     
}

In fact, if I do something like:

User::where(function($q){
                      $q->where('type', '=', 'dvp')
                        ->orWhere('type','=','ecp');
                      })
                      ->where(function($q){
                        $q->whereNotNull('lat')
                        ->whereNotNull('lng');
                      })
                      ->getByDistanceClean($lat,$lng, 'max_distance');

Then this won't work and it will throw an error which shows that the SQL statement has not been build correctly.

SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from users where (type = ? or type = ?) and (lat is not null and lng i' at line 1 (SQL: select *, ( 3959 * acos( cos( radians(52.495492) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(13.3436762) ) + sin( radians(52.495492) ) * sin( radians(lat) ) ) ) AS distance FROM users HAVING distance < 5 from users where (type = dvp or type = ecp) and (lat is not null and lng is not null) order by distance asc)

The problem is that from users appears twice at the end. Why is that? Is the top snippet really the best one can do when using DB::raw ?



via Chebli Mohamed

Aucun commentaire:

Enregistrer un commentaire