Reputation: 6058
Query where the problem lies
\DB::enableQueryLog();
$place = Place::near($user)->with(['services','services.registrable' => function (MorphTo $query) {
$query->where('distance_of_visibility', '<', \DB::raw('places.distance'));
}])->find(22);
\DB::disableQueryLog();
dd(\DB::getQueryLog());
Generated queries
First: The queries will calculate all the places in a given radius and add the calculated field distance to the select
select *, st_distance_sphere(`location`, ST_GeomFromText(0.000000 00.000000)) as distance from `places` where st_distance_sphere(`location`, ST_GeomFromText(0.000000 00.000000)) <= 5000 and `places`.`id` = 22 limit 1
Second: with
will eager-load the services
select * from `services` where `services`.`place_id` in (22)
Finally: with
will try to load registrable
but the eager-load gives an obvious error since places.distance doesn't exist in this scope
select * from information where distance_of_visibility < places.distance and information.id in (5)
which throw
PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'places.distance' in 'where clause'
What am I trying to do
Let's say the calculated field distance of a place returns the value 55 meters
I want to eager load the information (through the services) only when the distance_of_visibility is under those 55 meters.
So my question is: how can I make it work in the most efficient way. Calculate the distance take some querying time. I would try to avoid join table + recalculation. I guess there's a way to access to the previous queries results from $query
but I couldn't figure how.
Context in case you need more information
Place Model
1. It uses https://github.com/grimzy/laravel-mysql-spatial
2. Is hasMany
Service
3. It contain a scope that add the calculated field distance to the select:
/**
* Get the places near the user in a certain radius
* It also add the distance in the select statement
*
* @param SpatialBuilder $query
* @param Geolocalisable $geolocalisable
* @return SpatialBuilder
*/
public function scopeNear(SpatialBuilder $query, Geolocalisable $geolocalisable): SpatialBuilder
{
return $query
->distanceSphereValue('location', $geolocalisable->position())
->distanceSphere('location', $geolocalisable->position(), $geolocalisable->radiusInMeter());
}
Service Model
1. The Service belongsTo
a Place
2. The Service MorphTo
a Registrable
Registrable Model
1. There's no Registrable Model. It's a polymorphic relationship with multiple Models. In this example, you're seeing "Information"
2. Those Registrable Models morphOne
Service
Upvotes: 1
Views: 119
Reputation: 5050
Unfortunately what you're asking to do isn't possible with Eloquent.
The eager-load query is entirely separate from the initial query so any values retrieved are no longer available.
Your options are either to do a join in your constraint (which you indicated might not be performant), or load all the related models and then sort/filter those using PHP instead.
Upvotes: 1