Введение
Была у меня задача по оптимизации Dadata. И для этого пришлось прошестить множество файлов.
Это описание больше для разработчиков которые будут в будещем работать с dadata. Так же, в нем я опишу ту ошибку и из-за чего она была получена. Ниже представленны комментарии с отображением работы, а так же код из файлов и как он выполняется в проекте.
DadataGeoIP
и AddressDadata
Про файлы Это два файла в back-end которые используют библиотеку Dadata\DadataClient
.
-
Коротко про
DadataGeoIP
В этом файле описывается вывод адреса по IP сервиса Dadata. Методы в этом классе выполняютследующую функцию:
-поиск адреса по IP
-получить строну и регион по IP
Этот файл используется в трейде, новостях, модели, а так же на главной странице сайта. -
Коротко про
AddressDadata
В этом файле так же описывается вывод адреса по IP сервиса Dadata. Методы в этом классе выполняютследующую функцию:
-поиск адреса
-получение стары и регион по адресу
-получить id страны
-получить id региона
-получить id страны по названию страны
-получить всю инфомрмацию об огранизации по ИНН.
Отличия отDadataGeoIP
состоят в том, что объект этого класса чаще всего используется в редактирование профиля.
Класс DadataGeoIP
Класс DadataGeoIP исползуется в файлах Instance и GeoipConverter.
Начну с Instance. В классе Geoip_Instance dadata используется в четырех местах и все в одном месте - это метод getLocation. Данный метод возвращает город или страну или регион иначе false. В методе используется объект класса DadataCachedIP. С помощью этого объекта класса мы кэшируем информацию об IP адресе. Само кеширование используется при определение региона пользователя при заходе на сайт (Ремарка Класс используется только в связке с Instance.php).
Метод getLocation используется в самом же классе, для получения локации пользователя. Метод называется getUserLocation и описание у него следующая реализация: "Получить локацию пользователя, определенную по IP (для гостей) или из профиля для авторизованных". Данный метод используется в четырех местах.
- NewsModel;
- Model.php;
- StartpageModule.php;
- TradeModule.php
В Model в методе getUserLocation - "Получить локацию пользователя, определенную по IP (для гостей) или из профиля для авторизованных". И вот уже дальше метод пользуется везде. Пример отображения на главной старнице:
Про StartpageModule
В StartpageModule.php используется в методе beforeActionRun()
для того чтобы вывести переменнуб currentRegion
и выводится он главную страницу. И работает данный метод следующим образом:
Перед тем как запустить страницу, мы выводим переменную во View элемент currentRegion
из переменной $this->seoRegion
. Далее, происходит подключение javascript контроллера, который управляется с front-end. И после этого происходит нахождение региона. Изначально смотрим ту же самую переменную $this->seoRegion
(* В комментариях подписано что это глобальный регоион (поддомен)). И если такого региона нет, то он записывается в переменую $this->region
, которая в свою очередь отправляется во View элемент currentRegion
. Для наглядности вот сам метод:
protected function beforeActionRun()
{
parent::beforeActionRun();
$this->assign('currentRegion', $this->seoRegion);
$this->response->setPageController('startpage');
// Регион
if (!empty($this->seoRegion)) { // Глобальный регион (поддомен)
$this->region = $this->seoRegion;
$this->assign('currentRegion', $this->region);
} else {
// Автоматическое определение региона
$location = \Geoip_Instance::getUserLocation();
if (isset($location['city'])) {
$region = new GeoRegion($location['city']['region_id']);
$regionInfo = (new GeoRegionValidated($region))->exist() ? ($region)->info() : '';
$this->assign('defaultLocation', $regionInfo);
} elseif (isset($location['region'])) {
$region = $location['region'];
$this->assign('defaultLocation', $region);
}
}
}
И вот если у нас регон уже есть в переменной $this->seoRegion
, то тогда с помощью метода описанного выше, \Geoip_Instance::getUserLocation()
, получаем регион. И если кеш или dadata выведет нам город или регион, то они попадают в переменную View элемента defaultLocation
.
NewsModule.php
Файл Переходим к следующему файлу NewsModule.php
Он используется идентично как и в StartpageModule
, но с некоторыми доработками. Код файла NewsModule.php
:
/**
* Инициализация модуля.
*/
public function beforeActionRun()
{
$this->response->setPageController('news');
// Путь к объединённому файлу стилей модуля.
// Эксперимент по объединению стилей #8054.
$this->assign('cssOne', 'defstyle/20/news-page/style.css');
// Получение статики новостного сервиса.
$newsStatics = $this->access->statics();
$this->assign('newsStatics', $newsStatics);
$this->assign('showCalcBanner', 'surveys');
// Регион
if (!empty($this->seoRegion)) { // Глобальный регион (поддомен)
$this->region = $this->seoRegion;
$this->assign('currentRegion', $this->region);
} else {
// Автоматическое определение региона
$location = \Geoip_Instance::getUserLocation();
if (isset($location['city'])) {
$region = new GeoRegion($location['city']['region_id']);
$region = (new GeoRegionValidated($region))->exist() ? $region->info() : '';
$this->assign('defaultLocation', $region);
} elseif (isset($location['region'])) {
$region = $location['region'];
$this->assign('defaultLocation', $region);
}
}
// Сортировка рубрик и установка параметров сервиса в шаблоне.
// $clientParams = array_diff_key($service->getClientParams(), ['authCode' => true]);
// $clientParams['sections'] = array_intersect(
// array_keys($newsStatics['sectionList']),
// $clientParams['sections']
// );
// $this->assign('clientParams', $clientParams);
$this->assign('currUserProfile', \ORM_User_profile::getById($this->user->id));
}
Все то, что связано с dadata - все осталось как прежде. Остальные изменения больше относятся к front-end части.
TradeModule.php и использование Dadata
Файл Метод getUserLocation
используется так же и в объявлениях. Используется он методе listAction
. Данный экшен выводит список объявлений с фильтрами и без, а так же все параметры GET сортирует по алфавиту для работы SEO.
Рализация dadata выполняется таким образом, что ищет локацию пользователя. И в дальшейшем в коде переадресует пользователя на поддомен. Например, 'https://ufa.meatinfo.m16/trade?from=header'
.
Работает - это все дело очень просто. Изначально, пока пользователь не задал свой адресс, он будет пытаться вытащить его из IP и записывать в куки. Ну и таким образом после того как пользователь выбрал свой город или регион или хотя бы страну. Все данные записываются в куки и даже если пользов
атель закроет сайт и снова зайдет в объявление, то будет происходить редирект на поддомен который указал пользователь.
Следующий файл AddressDadata:
Подписан он как "Адреса сериса dadata"
Методы в этом классе выполняют следующий функционал:
-поиск адреса
-получение стары и регион по адресу
-получить id страны
-получить id региона
-получить id страны по названию страны
-получить всю инфомрмацию об огранизации по ИНН
Данный класс используется и в Профиле и в Актах и еще в 11 местах:
Следующий файл AddressDadata:
Подписан он как "Адреса сериса dadata"
Методы в этом классе выполняют следующий функционал:
-поиск адреса
-получение стары и регион по адресу
-получить id страны
-получить id региона
-получить id страны по названию страны
-получить всю инфомрмацию об огранизации по ИНН
Данный класс используется и в Профиле и в Актах и еще в 11 местах:
Так как AddressDadata находится в ProfileModule, начну с него:
Подписан данный файл как "Новая версия профиля."
В профиле есть метод addressSugggestAction. Описания у него нет, но функционал у него следующий - получить из формы GET парметр с названием term и получить данные по конкретному адресу. Метод выводит JSON массивю. Данный метод либо не используется, либо я не нашел (Искал с помощью PHPShtorm->Find in Files).
Следующий метод подписан - "Получить страну и регион по адресу". Метод практическии идентичен тому что был выше, но отличается сам GET, он передает уже address.Используется данный метод много где, но в основном в profile.js.
proffile.js - это Скрипт для формы редактирования профиля. Так что его трогать не стану.
Дальше, следующий файл от AddressDadata - LitecatModule.
Подписан он как "Модуль для связи HTML-фронтенда и JSON-сервиса каталога компании."
Здесь используеются такие же методы как и в ProfileModule - addressSuggestAction и addressInfoAction.
Ну да ладно, AddressDadata так же аходится в MainpageModule. И здесь он используется в двух местах.
Сам MainpageModule подписан как "Главная страница". Так же, отмечу, что это файл Актов, т.е. Actmaker.
Первое место где встречается dadata - это само подключение, здесь вопросов нет. Второе место в методе "Ввести новый счет". В данном месте проверяется ИНН акта, и если акт содержит ошибки в ИНН, либо такой организации не существует, то выведется ошибка и менеджер будет проинформаирован об этом и загрузка XML файла будет не доступна.
Следующий файл doStuffDelta - это файл для проверки некоторых скриптов. Используется dadata в 5 местах, но большая часть кода закоментированна, но есть и одна не закоментированная часть. Находится она в методе dataAddressDelta. Метод нигде не используется и трогать его не имеет смысла.
И последний файл - это readCsvCompany. Описание файла - "Забор данных о компании из csv файла companies.csv". В коммите нашел следующие описание - "Скрипт читающий csv и создающий компанию в базовом виде". Данный скрипт использовался несколько раз. На данный момент не используется, так что смысла его трогать - нет.
В AddressDadata было все рассмотренно все. На текущий момент (январь 2023).
Вывод
Вывод данной работы следующий. Из-за того, что большая часть пользователей, а большая часть из них - это гости, индексируются с помощью dadata, а именно в файле Instance.php
- private static function getLocation($ip)
ссылка на метод