refactor: extract HaversineQuery helper, fix LL bind quirk
The 5 haversine SQL fragments duplicated across StationController and NationalFuelPredictionService disagreed on float-clamping (LEAST only, GREATEST/LEAST, vs. CASE WHEN). Centralised in App\Services\HaversineQuery with the safe GREATEST(-1.0, LEAST(1.0, …)) form everywhere. withinKm() embeds the radius as a numeric literal (sprintf %F) because PDO + SQLite binds float parameters as strings by default, which breaks numeric comparison against the haversine expression — a NULL filter would silently match all rows. Coordinates remain bound positionally. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ use App\Http\Resources\Api\StationResource;
|
||||
use App\Models\Search;
|
||||
use App\Models\Station;
|
||||
use App\Models\User;
|
||||
use App\Services\HaversineQuery;
|
||||
use App\Services\NationalFuelPredictionService;
|
||||
use App\Services\PlanFeatures;
|
||||
use App\Services\PostcodeService;
|
||||
@@ -43,14 +44,12 @@ class StationController extends Controller
|
||||
$radius = $request->radius();
|
||||
$sort = $request->sort();
|
||||
|
||||
[$distanceSql, $distanceBindings] = HaversineQuery::distanceKm($lat, $lng);
|
||||
|
||||
$all = Station::query()
|
||||
->selectRaw(
|
||||
'stations.*, spc.price_pence, spc.fuel_type, spc.price_effective_at,
|
||||
(6371 * acos(GREATEST(-1.0, LEAST(1.0,
|
||||
cos(radians(?)) * cos(radians(lat)) * cos(radians(lng) - radians(?))
|
||||
+ sin(radians(?)) * sin(radians(lat))
|
||||
)))) AS distance_km',
|
||||
[$lat, $lng, $lat],
|
||||
"stations.*, spc.price_pence, spc.fuel_type, spc.price_effective_at, {$distanceSql} AS distance_km",
|
||||
$distanceBindings,
|
||||
)
|
||||
->join('station_prices_current as spc', function (JoinClause $join) use ($fuelType): void {
|
||||
$join->on('stations.node_id', '=', 'spc.station_id')
|
||||
|
||||
Reference in New Issue
Block a user