Skip to content

Instantly share code, notes, and snippets.

@reddo
Last active August 25, 2023 02:32
Show Gist options
  • Save reddo/0157a184d47e7f3f0caa7d253de432ff to your computer and use it in GitHub Desktop.
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`
<?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