-
-
Save Koc/3016704 to your computer and use it in GitHub Desktop.
| <?php | |
| namespace Myako\Geographical\Functions; | |
| use Doctrine\ORM\Query\AST\Functions\FunctionNode; | |
| use Doctrine\ORM\Query\Lexer; | |
| /** | |
| * "DISTANCE" "(" LatitudeFrom, LongitudetFrom, LatitudeTo, LongitudeTo ")" | |
| * | |
| * @author Konstantin.Myakshin <[email protected]> | |
| */ | |
| class DistanceFunction extends FunctionNode | |
| { | |
| protected $fromLat; | |
| protected $fromLng; | |
| protected $toLat; | |
| protected $toLng; | |
| public function parse(\Doctrine\ORM\Query\Parser $parser) | |
| { | |
| $parser->match(Lexer::T_IDENTIFIER); | |
| $parser->match(Lexer::T_OPEN_PARENTHESIS); | |
| $this->fromLat = $parser->ArithmeticPrimary(); | |
| $parser->match(Lexer::T_COMMA); | |
| $this->fromLng = $parser->ArithmeticPrimary(); | |
| $parser->match(Lexer::T_COMMA); | |
| $this->toLat = $parser->ArithmeticPrimary(); | |
| $parser->match(Lexer::T_COMMA); | |
| $this->toLng = $parser->ArithmeticPrimary(); | |
| $parser->match(Lexer::T_CLOSE_PARENTHESIS); | |
| } | |
| public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker) | |
| { | |
| $earthDiameterInKM = 1.609344 * 3956 * 2; | |
| $sql = '('.$earthDiameterInKM.' * ASIN(SQRT(POWER(' . | |
| 'SIN(('.$this->fromLat->dispatch($sqlWalker).' - ABS('.$this->toLat->dispatch($sqlWalker).')) * PI() / 180 / 2), 2) + ' . | |
| 'COS('.$this->fromLat->dispatch($sqlWalker).' * PI() / 180) * COS(ABS('.$this->toLat->dispatch($sqlWalker).') * PI() / 180) * ' . | |
| 'POWER(SIN(('.$this->fromLng->dispatch($sqlWalker).' - '.$this->toLng->dispatch($sqlWalker).') * PI() / 180 / 2), 2) ' . | |
| ')))'; | |
| return $sql; | |
| } | |
| } |
This will trigger the following error in conjunction with doctrine's spatial library:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens"
i think you have to use ArithmeticExpression() instead of ArithmeticPrimary()
@see https://github.com/craue/CraueGeoBundle/blob/master/Doctrine/Query/Mysql/GeoDistance.php#L38
Important: This function is currently wrong and won't work for any negative latitudes. The ABS-functions need to be removed and then it seems to work correctly. I compared it with the original formula for this calculation and there were no ABS-functions used. I am not sure if there is a good reason why you did use them, but after trying a lot of different geo positions and searching for this error for a few hours now I found out that removing them solves the issue.
Thank you very much! Very helpful.
To register the function use:
Assuming that you have an entity
YourBundle:Citywith aname,latitude, andlongitudeattributes you could query all cities in the proximity of 100 km around the point53.66047260, 9.74414190with: