From e09910f87953743c4c6e77a3db97846fd7d96d50 Mon Sep 17 00:00:00 2001 From: William DURAND Date: Sun, 2 Feb 2014 01:01:29 +0100 Subject: [PATCH] Fix `filterByDistanceFrom()` Replaces #29 --- ...GeocodableBehaviorQueryBuilderModifier.php | 6 ++++- src/templates/queryFilterByDistanceFrom.php | 23 +++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/GeocodableBehaviorQueryBuilderModifier.php b/src/GeocodableBehaviorQueryBuilderModifier.php index a459925..25a59b5 100644 --- a/src/GeocodableBehaviorQueryBuilderModifier.php +++ b/src/GeocodableBehaviorQueryBuilderModifier.php @@ -57,10 +57,14 @@ public function addFilterByDistanceFrom($builder) $builder->declareClass('Criteria', 'PDO'); $queryClassName = $builder->getStubQueryBuilder()->getClassname(); + $peerClassName = $builder->getStubPeerBuilder()->getClassname(); return $this->behavior->renderTemplate('queryFilterByDistanceFrom', array( 'queryClassName' => $queryClassName, - 'defaultUnit' => $this->getDefaultUnit($builder) + 'defaultUnit' => $this->getDefaultUnit($builder), + 'peerClassName' => $peerClassName, + 'longitudeColumnConstant' => $this->behavior->getColumnConstant('longitude_column', $builder), + 'latitudeColumnConstant' => $this->behavior->getColumnConstant('latitude_column', $builder), )); } diff --git a/src/templates/queryFilterByDistanceFrom.php b/src/templates/queryFilterByDistanceFrom.php index c0b531e..f7180e3 100644 --- a/src/templates/queryFilterByDistanceFrom.php +++ b/src/templates/queryFilterByDistanceFrom.php @@ -12,8 +12,27 @@ */ public function filterByDistanceFrom($latitude, $longitude, $distance, $unit = , $comparison = Criteria::LESS_THAN) { + if (::MILES_UNIT === $unit) { + $earthRadius = 3959; + } elseif (::NAUTICAL_MILES_UNIT === $unit) { + $earthRadius = 3440; + } else { + $earthRadius = 6371; + } + + $sql = 'ABS(%s * ACOS(%s * COS(RADIANS(%s)) * COS(RADIANS(%s) - %s) + %s * SIN(RADIANS(%s))))'; + $preparedSql = sprintf($sql, + $earthRadius, + cos(deg2rad($latitude)), + $this->getAliasedColName(), + $this->getAliasedColName(), + deg2rad($longitude), + sin(deg2rad($latitude)), + $this->getAliasedColName() + ); + return $this - ->withDistance($latitude, $longitude, $unit) - ->where(sprintf('Distance %s ?', $comparison), $distance, PDO::PARAM_STR) + ->withColumn($preparedSql, 'Distance') + ->where(sprintf('%s %s ?', $preparedSql, $comparison), $distance, PDO::PARAM_STR) ; }