Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Loach's avatar
Level 11

Converting SQL Query into Eloqeunt

I have the following sql query I need to convert to eloquent. I have the "lat" and "lng" fields in the user table. Basically I need to select all users within the 25 mile radius.

SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance FROM markers HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;
0 likes
33 replies
Loach's avatar
Level 11

Searching I think I need to use "whereRaw"? Any help on that?

JoaoPedroAS51's avatar
Level 4

First you need to go to your config/database.php and set strict to false. Then try to use this, it's something like that:

\App\User::selectRaw('id, ( 3959 * acos( cos( radians(37) ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians(-122) ) + sin( radians(37) ) * sin( radians( latitude ) ) ) ) distance')->havingRaw('distance < 25')->orderBy('distance')->take(20)->get();
2 likes
Loach's avatar
Level 11

I will try this when I get home. I am away right now. Will let you know how it goes.

jlrdw's avatar

I would use your original query with getPdo ().

Loach's avatar
Level 11

I added 'AS distance' to that and am getting an error.

Non-grouping field 'distance' is used in HAVING clause (SQL: select ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance from `users` where (`role_id` = 2 and `ban_user` = 0) having distance < 25)
Loach's avatar
Level 11

Actually i forgot to set strict to "false" as you mentioned. I am not getting any errors with that query, but now I have to tie it into my actual code to see if it is working.

Loach's avatar
Level 11

Does not seem to get the results with my code. I am not sure I am passing variables correctly. Does anything look off?

  $theCity = City::where('region_id',$request["region_id"])->where('name',$request['city_id'] )->first();
            $theLat = $theCity->latitude;
            $theLong = $theCity->longitude;
            $theRadius = $request['radius'];

             $user->selectRaw('( 3959 * acos( cos( radians("{$theLat}") ) * cos( radians( lat ) ) * cos( radians(lng ) - radians("{$theLong}") ) + sin( radians("{$theLat}") ) * sin( radians( lat ) ) ) ) AS distance')
               ->havingRaw('distance <= "{$theRadius}"');

            return view('frontend.search_results')->with(['results'=>$user->get()]);
Loach's avatar
Level 11

Yep I am passing the variables wrong. DD the query yields the following.

"select ( 3959 * acos( cos( radians("{$theLat}") ) * cos( radians( lat ) ) * cos( radians(lng ) - radians("{$theLong}") ) + sin( radians("{$theLat}") ) * sin( radians( lat ) ) ) ) AS distance from `users` where (`role_id` = ? and `ban_user` = ?) having distance <= "{$theRadius}"
Loach's avatar
Level 11

OK here is the final code. But I am getting an error. "Trying to get property of non-object". If I remove this code my query works as usual.

   $theCity = City::where('region_id',$request["region_id"])->where('name',$request['city_id'] )->first();
            $theLat = $theCity->latitude;
            $theLong = $theCity->longitude;
            $theRadius = $request['radius'];

        $user->selectRaw("( 3959 * acos( cos( radians({$theLat}) ) * cos( radians( lat ) ) * cos( radians(lng ) - radians({$theLong}) ) + sin( radians({$theLat}) ) * sin( radians( lat ) ) ) ) AS distance")
               ->havingRaw("distance <= {$theRadius}");
Loach's avatar
Level 11

Wonder if it could be because of 'role_id' = ? and 'ban_user' = ?. Those should be 2 and 0 respectively.

Loach's avatar
Level 11

How do you mean? dd($user) ? I am just calling $user-get()

Here is my complete code. I am unsure about the User::query() thing never seen it before, but another coder added that.

  public function search(Request $request){


      $user = User::query();
      $matchThese=['role_id'=>2,'ban_user'=>0];
      $user->where($matchThese);


        if(isset($request['city_id'])){
             $theCity = City::where('region_id',$request["region_id"])->where('name',$request['city_id'] )->first();
            $theLat = $theCity->latitude;
            $theLong = $theCity->longitude;
            $theRadius = $request['radius'];


          $user->selectRaw("( 3959 * acos( cos( radians({$theLat}) ) * cos( radians( lat ) ) * cos( radians(lng ) - radians({$theLong}) ) + sin( radians({$theLat}) ) * sin( radians( lat ) ) ) ) AS distance")
                ->havingRaw("distance <= {$theRadius}");
          }

            return view('frontend.search_results')->with(['results'=>$user->get()]);
   }
JoaoPedroAS51's avatar

What returns if you do dd($user->get()) inside and outside the if(isset($request['city_id'])). Just trying to check if this if is working and if the $user->get() is working .

Loach's avatar
Level 11

Collection {#719 ▼
  #items: array:3 [▼
    0 => User {#714 ▶}
    1 => User {#713 ▶}
    2 => User {#712 ▶}
  ]
}

Must be an error elsewhere?

JoaoPedroAS51's avatar

Maybe the isset is not working, if outside the if doesn't show the same thing.

Loach's avatar
Level 11

I removed most of the code from my search_results.blade.php and it is showing "your query returned 3 results". So I guess it is working. I just have to add the code back in and see what is causing the problem.

JoaoPedroAS51's avatar

If it still causing problems post your view, so I can try to help you.

tisuchi's avatar

@Loach

Have you tried this?

DB::select(`id`)
        ->addSelect(DB::raw(`( 3959 * acos( cos( radians(37) ) * cos( radians(lat) ) * cos( radians(lng) - radians(-122) ) + sin( radians(37) ) * sin( radians(lat) ) ) )`  as distance))
        ->from(`markers`)
        ->having(`distance`, `<`, 25)
        ->orderByRaw(`distance ASC`)
        ->limit(20)
        ->get();
1 like
Loach's avatar
Level 11

Although it is showing 3 users they have no attributes like "firstname", "lastname", etc. It is only showing 'distance' as an attribute which is strange. But it seems to be getting the correct number of users based on radius.

  #items: array:2 [▼
    0 => User {#719 ▼
      #fillable: array:3 [▼
        0 => "name"
        1 => "email"
        2 => "password"
      ]
      #hidden: array:2 [▼
        0 => "password"
        1 => "remember_token"
      ]
      #connection: "mysql"
      #table: null
      #primaryKey: "id"
      #keyType: "int"
      +incrementing: true
      #with: []
      #withCount: []
      #perPage: 15
      +exists: true
      +wasRecentlyCreated: false
      #attributes: array:1 [▼
        "distance" => 0.0
      ]
      #original: array:1 [▼
        "distance" => 0.0
      ]
      #casts: []
      #dates: []
      #dateFormat: null
      #appends: []
      #events: []
      #observables: []
      #relations: []
      #touches: []
      +timestamps: true
      #visible: []
      #guarded: array:1 [▶]
      #rememberTokenName: "remember_token"
    }
Loach's avatar
Level 11

Outside the if it shows the correct attributes.

Loach's avatar
Level 11

I added a "*" to the beginning of the query. I guess I left off that part it seems to add the attributes back, but I have to see if it works with the rest of the code. So I guess your first post was right.

$user->selectRaw("*,( 3959 * acos( cos( radians({$theLat}) ) * cos( radians( lat ) ) * cos( radians(lng ) - radians({$theLong}) ) + sin( radians({$theLat}) ) * sin( radians( lat ) ) ) ) AS distance")
                ->havingRaw("distance <= {$theRadius}");
Loach's avatar
Level 11

It seems to work with all my other search parameters. Thanks so much for the help! I will accept your first post as the correct answer.

Loach's avatar
Level 11

Actually i do have one more question. Those lat,lng,and radius are coming from a form. Since we are using raw queries do i need to be concerned with sql injection?

Next

Please or to participate in this conversation.