|
|
# Введение
|
|
|
Была у меня [задача](http://lab.inline-ltd.ru/m16tech/m16/-/issues/14875) по оптимизации 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 (для гостей) или из профиля для авторизованных". И вот уже дальше метод пользуется везде. Пример отображения на главной старнице:
|
|
|
![изображение](uploads/8c61a9a530350201336112088b187773/изображение.png)
|
|
|
![изображение](uploads/d3f38cec03c4b9d39311e90d010af45b/изображение.png)
|
|
|
|
|
|
Пример отображения в трейде:
|
|
|
![изображение](uploads/03d11fde7cea5c04b2d738c7a9fbfa58/изображение.png)
|
|
|
|
|
|
### Про StartpageModule
|
|
|
В StartpageModule.php используется в методе `beforeActionRun()` для того чтобы вывести переменнуб `currentRegion` и выводится он главную страницу. И работает данный метод следующим образом:
|
|
|
Перед тем как запустить страницу, мы выводим переменную во View элемент `currentRegion` из переменной `$this->seoRegion`. Далее, происходит подключение javascript контроллера, который управляется с front-end. И после этого происходит нахождение региона. Изначально смотрим ту же самую переменную `$this->seoRegion` (* В комментариях подписано что это глобальный регоион (поддомен)). И если такого региона нет, то он записывается в переменую `$this->region`, которая в свою очередь отправляется во View элемент `currentRegion`. Для наглядности вот сам метод:
|
|
|
```php
|
|
|
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`:
|
|
|
```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 и записывать в куки. Ну и таким образом после того как пользователь выбрал свой город или регион или хотя бы страну. Все данные записываются в куки и даже если пользов
|
|
|
атель закроет сайт и снова зайдет в объявление, то будет происходить редирект на поддомен который указал пользователь.
|
|
|
![изображение](uploads/f3e799c4a6f3f5acac454ec78b3d9d58/изображение.png)
|
|
|
|
|
|
# Следующий файл AddressDadata:
|
|
|
Подписан он как "Адреса сериса dadata"
|
|
|
Методы в этом классе выполняют следующий функционал:
|
|
|
-поиск адреса
|
|
|
-получение стары и регион по адресу
|
|
|
-получить id страны
|
|
|
-получить id региона
|
|
|
-получить id страны по названию страны
|
|
|
-получить всю инфомрмацию об огранизации по ИНН
|
|
|
Данный класс используется и в Профиле и в Актах и еще в 11 местах:
|
|
|
![изображение](uploads/74d101ae6a853691fbce7bc9f9de4265/изображение.png)
|
|
|
|
|
|
|
|
|
# Следующий файл AddressDadata:
|
|
|
Подписан он как "Адреса сериса dadata"
|
|
|
Методы в этом классе выполняют следующий функционал:
|
|
|
-поиск адреса
|
|
|
-получение стары и регион по адресу
|
|
|
-получить id страны
|
|
|
-получить id региона
|
|
|
-получить id страны по названию страны
|
|
|
-получить всю инфомрмацию об огранизации по ИНН
|
|
|
Данный класс используется и в Профиле и в Актах и еще в 11 местах:
|
|
|
![изображение](/uploads/560622d524fae45d8036fe627eccbefb/изображение.png)
|
|
|
|
|
|
|
|
|
Так как 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)` [ссылка на метод](http://lab.inline-ltd.ru/m16tech/m16all/-/blob/master/m16/lib/Geoip/Instance.php#L118) |
|
|
\ No newline at end of file |