• Jobs
  • About Us
  • professionals
    • Home
    • Jobs
    • Courses and challenges
    • Questions
    • Teachers
  • business
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

466
Views
Laravel Eloquent - How to return a calculated value inside a scope query as a model column or collection property

I'm trying to get a list of users that are near the authenticated user and also return the distance between them using Laravel's Eloquent. I got it to work using raw SQL, but now I'm almost there making it work properly using mostly eloquent.

So, on the User model I have this method:

public function getUsersAround($coordinates, $radius = 5)
{
    return $this->whereHas('location', function ($query) use ($coordinates, $radius) {
            $query->distance($coordinates, $radius);
        })->paginate(10);
}

Then on the Location model, I have the following scope:

public function scopeDistance($query, $coordinates, $radius)
{
    return $query
        ->join('profiles', 'profiles.id', '=', 'locations.profile_id')
        ->having('distance', '<', $radius)
        ->selectRaw("profile_id,
                 (6371 * ACOS(COS(RADIANS($coordinates->latitude))
                       * COS(RADIANS(latitude))
                       * COS(RADIANS(longitude) - RADIANS($coordinates->coordinates))
                       + SIN(RADIANS($coordinates->latitude))
                       * SIN(RADIANS(latitude)))) AS distance")
        ->orderBy('distance', 'asc');
}

So, all the users in the radius are being returned correctly, but I also want to add the calculated distance to each returned user.

What's strange is that if I dd($query->distance($coordinates, $radius)); I see all the users + a new distance property on each user object (with the correct value), but if I just return the query and dd(auth()->user()->getUsersAround($coordinates, $radius)) inside the controller, the distance property is not there anymore.

Is there a way to return the calculated distance inside the scope query and persist it on the Users object when returning the list of users?

Thanks!

about 3 years ago · Santiago Trujillo
2 answers
Answer question

0

If you want to include the distance in the results, you need the load the location relation with the distance attribute. Since you are already selecting the distance in the query scope on the Location model, you can achieve this quite easily:

public function getUsersAround($coordinates, $radius = 5)
{
    return $this->whereHas('location', function ($query) use ($coordinates, $radius) {
        $query->distance($coordinates, $radius);
    })->with([
        'location' => function ($query) use ($coordinates, $radius) {
            $query->select('locations.*')->distance($coordinates, $radius);
        }
    ])->paginate(10);
}

Notice the with('location'), which eager loads the Location model. I've added a select('locations.*') so that the location relation will have its own attributes, and the distance($coordinates, $radius) will also select the profile_id and the distance attributes.

So when you are calling auth()->user()->getUsersAround($coordinates, $radius) inside your controller, you can access the distance attribute with $user->location->distance:

$users = auth()->user()->getUsersAround($coordinates, $radius);

foreach ($users as $user) {
    $distance = $user->location->distance;
}
about 3 years ago · Santiago Trujillo Report

0

That's because you are using get() inside a scope which is not correct. local scopes are intended to define common sets of constraints (like for filtering data). check the documentation on local scopes for more detail.

To add something to a select result, you can use addSelect.

about 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Recommend me some offers
I have an error