Last active
August 25, 2023 02:32
-
-
Save reddo/0157a184d47e7f3f0caa7d253de432ff to your computer and use it in GitHub Desktop.
A directus.io custom endpoint to get distance based on coordinates. Put this file in `public/extensions/custom/endpoints/` and access it via `{{api_url}}/custom/locations?lat=LATITUDE_TO_CHECK_AGAINST&lng=LONGITUDE_TO_CHECK_AGAINST`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use Directus\Application\Http\Request; | |
use Directus\Application\Http\Response; | |
use Directus\Services\ItemsService; | |
use Zend\Db\Adapter\Adapter; | |
return [ | |
// The endpoint path: | |
// '' means it is located at: `/custom/<endpoint-id>` | |
// '/` means it is located at: `/custom/<endpoint-id>/` | |
// 'test' and `/test` means it is located at: `/custom/<endpoint-id>/test | |
// if the handler is a Closure or Anonymous function, it's binded to the app container. Which means $this = to the app container. | |
'' => [ | |
'method' => 'GET', | |
'handler' => function (Request $request, Response $response) { | |
$container = \Directus\Application\Application::getInstance()->getContainer(); | |
$dbConnection = $container->get('database'); | |
$acl = $container->get('acl'); | |
$itemsService = new ItemsService($this); | |
$params = $request->getQueryParams(); | |
if ($acl->canRead('locations')) { | |
$lat = "json_extract(coordinates, '$.lat')"; | |
$lng = "json_extract(coordinates, '$.lng')"; | |
// 6731000 is the earth radius in meters | |
$sql = "SELECT id," | |
. " 6731000 * 2 * ASIN(SQRT(POWER(SIN((" . $params["lat"] . " - abs(" . $lat . ")) * pi()/180 / 2), 2)" | |
. " + COS(" . $params["lng"] . " * pi()/180 ) * COS(abs(" . $lat . ") * pi()/180)" | |
. " * POWER(SIN((" . $params["lng"] . " - " . $lng . ") * pi()/180 / 2), 2) )) as distance" | |
. " FROM `locations`"; | |
// this is some custom filter applicable in my case | |
// if (isset($params["filter"]["city"])) { | |
// $sql = $sql . " WHERE city = " . $params["filter"]["city"]["eq"]; | |
// } | |
if (isset($params["distance"])) { | |
$sql = $sql . " HAVING distance < " . $params["distance"]; | |
} | |
// print_r($sql); | |
$result = $dbConnection->query($sql, Adapter::QUERY_MODE_EXECUTE); | |
$result = $result->toArray(); | |
} | |
$locations = $itemsService->findAll('locations', $params); | |
$final = array_replace_recursive($locations["data"], $result); | |
return $response->withJson([ | |
'data' => $final, | |
]); | |
} | |
], | |
]; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment