Налаштування геолокаційного визначення найближчого магазину 1С-Бітрікс

Наша компанія займається розробкою, підтримкою та обслуговуванням рішень на Бітрікс та Бітрікс24 будь-якої складності. Від простих односторінкових сайтів до складних інтернет-магазинів, CRM систем з інтеграцією 1С та телефонії. Досвід розробників підтверджено сертифікатами від вендора.
Пропоновані послуги
Показано 1 з 1 послугУсі 1626 послуг
Налаштування геолокаційного визначення найближчого магазину 1С-Бітрікс
Проста
~1 робочий день
Часті питання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Розробка на базі Бітрікс, Бітрікс24, 1С для компанії Development of an Online
    585
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Розробка на базі 1С Підприємство для компанії МИРСАНБЕЛ
    751
  • image_crm_dolbimby_434_0.webp
    Розробка сайту на CRM Бітрікс24 для компанії DOLBIMBY
    657
  • image_crm_technotorgcomplex_453_0.webp
    Розробка на базі Бітрікс24 для компанії ТЕХНОТОРГКОМПЛЕКС
    989

Налаштування геолокаційного визначення найближчого магазину 1С-Bitrix

Користувач відкриває сторінку «Наші магазини» та бачить список з 30 адрес без якого-небудь порядку. Він живе в Мінську, а перші п'ять магазинів у списку — Москва. Здавалося б, банальна завдання — показати найближчі — на практиці упирається в точність геолокації, розрахунок відстаней та зберігання координат магазинів в Bitrix.

Зберігання даних магазинів

В Bitrix магазини зберігаються у двох місцях залежно від використовуваного функціоналу:

Модуль sale, торгові точки: таблиця b_sale_store з полями ID, TITLE, ADDRESS, GPS_N (широта), GPS_S (довгота). Це стандартна структура для точок самовивозу.

Інфоблок магазинів: якщо магазини оформлені як елементи інфоблоку, координати зазвичай зберігаються в користувацьких властивостях типу String або в спеціалізованих полях типу Map (при наявності сторонніх модулів).

Для розрахунку відстаней потрібні числові координати. Якщо вони зберігаються в рядковій властивості інфоблоку у форматі «53.9045, 27.5615» — при виборці їх доведеться парсити, що незручно. Правильне рішення: зберігати широту та довготу у двох окремих числових властивостях або використовувати b_sale_store.GPS_N / b_sale_store.GPS_S.

Визначення координат користувача

Два підходи:

Браузерна геолокація (Geolocation API): точна, до 50 метрів, але вимагає дозволу користувача. Асинхронна — не можна використовувати при серверному рендерингу.

IP-геолокація: працює без запиту дозволу, точність — до міста/району. В Bitrix вбудований модуль location з базою GeoIP (b_geocode_city, b_geocode_country). Метод \Bitrix\Location\Service\FormatService::getInstance() працює з адресами, для IP-геолокації використовується \Bitrix\Main\Service\GeoIp\Manager::getLocationByIp().

$location = \Bitrix\Main\Service\GeoIp\Manager::getLocationByIp(
    \Bitrix\Main\Context::getCurrent()->getRequest()->getRemoteAddress()
);

$userLat = $location['LATITUDE'] ?? null;
$userLon = $location['LONGITUDE'] ?? null;

Розрахунок відстаней: формула Хаверсина у SQL

Найефективніший підхід — рахувати відстані прямо у SQL-запиті. Формула Хаверсина для PostgreSQL:

SELECT
    id,
    title,
    gps_n AS lat,
    gps_s AS lon,
    (
        6371 * acos(
            cos(radians(:user_lat)) * cos(radians(gps_n)) *
            cos(radians(gps_s) - radians(:user_lon)) +
            sin(radians(:user_lat)) * sin(radians(gps_n))
        )
    ) AS distance_km
FROM b_sale_store
WHERE active = 'Y'
  AND gps_n IS NOT NULL
  AND gps_s IS NOT NULL
ORDER BY distance_km
LIMIT 5;

Для MySQL синтаксис аналогічний. На PostgreSQL додатково можна використовувати розширення earthdistance з cube, що швидше для великих наборів точок.

Через ORM Bitrix прямий SQL викликається через \Bitrix\Main\Application::getConnection()->query(). Готового вираження Хаверсина в D7 ORM немає — доведеться використовувати ExpressionField з raw SQL або нативний запит.

Фронтенд: два кроки

  1. При завантаженні сторінки — показуємо магазини, відсортовані за IP-геолокацією (серверна сортування, миттєво).
  2. Після отримання точних координат через navigator.geolocation.getCurrentPosition() — пересортовуємо через AJAX-запит до компонента з параметрами lat та lon.
navigator.geolocation.getCurrentPosition(function(pos) {
    fetch('/ajax/nearest-stores/?lat=' + pos.coords.latitude + '&lon=' + pos.coords.longitude)
        .then(r => r.json())
        .then(stores => renderStoreList(stores));
});

Компонент-обробник AJAX читає lat/lon з GET, виконує SQL з Хаверсином, повертає JSON. В Bitrix це реалізується через компонент з параметром ajax_mode = Y або через власний endpoint у /local/ajax/.

Що ми налаштовуємо

  • Перевірку наявності координат у b_sale_store або інфоблоці магазинів, їх заповнення
  • SQL-запит з формулою Хаверсина через Application::getConnection()
  • IP-геолокацію через GeoIp\Manager для первинної сортування без дозволу користувача
  • AJAX-endpoint для пересортування після отримання точних координат браузера
  • Кешування результату для кожної пари координат (округленої до 0.01 градуса)