Для нового пользователя отображаются не нужные данные, так как данные берутся из кеша предыдущего пользователя

Я сделал кастомный модуль, отображающий погоду в конкретном городе.

Но я получил эти комментарии после проверки кода:

1. Интересный вопрос, что происходит с вашими данными кеша, если на сайт сначала заходит человек из города Лондон, а потом Париж?

Я так понимаю, это значит, что человек из Парижа, когда зайдет на сайт, увидит погоду в Лондоне, потому что она будет взята из кеша. Но я клал данные в кеш, чтобы не было слишком много запросов, один раз сделал запрос, положил данные в кеш, а в следующий раз уже брал данные из кеша.

2. В небольшой функции вы дважды вызываете конечную точку http://ip-api.com/json/. Что происходит, когда сайт посещает тысяча человек в минуту?

Вот не понимаю в чем проблема. Если это означало, что лимит подключений к ресурсу будет исчерпан, то как решить эту проблему? В функции getCity() поместить данные в кеш так же, как я делаю в функции build()? Но тут вылезает та же проблема, что и в первой реплике, если на сайт зайдет человек из другого города, то будут взяты данные из кеша (название города Лондона), а не название его реального города. Как тогда быть?

Подскажите, пожалуйста, что нужно изменить в моем коде? Ниже я напишу немного урезанный код для своего php файла. Полная версия здесь: https://phpsandbox.io/n/sweet-forest-1lew-1wmof

// ....
use Drupal\Core\Cache\CacheBackendInterface;
use GuzzleHttp\Client;

//....

  public function getCity() {

    $ip = '193.62.157.66';  // static because for testing

    try {
      $response_ip = $this->httpClient->get('http://ip-api.com/json/' . $ip);
      $response_data_ip = $response_ip->getBody();
      $data_ip = json_decode($response_data_ip);

      if ($data_ip->status == 'success') {
        return $data_ip->city;
      }
      else {
        return $this->configFactory->get('sydneypro_weather.settings')->get('weather_city');
      }

    }
    catch (RequestException $e) {
      return FALSE;
    }

  }

  public function build() {
    $client = $this->httpClient;
    $api_key = $this->configFactory->get('sydneypro_weather.settings')->get('weather_api_key');
    $cid = 'sydneypro_weather';
    $weather_config = $this->configFactory->get('sydneypro_weather.settings');

    if (!$weather_config) {
      $this->logger->get('sydneypro_weather')->error('Config "sydneypro_weather.settings" is missing4');
      return [];
    }

    if (empty($api_key) || empty($this->getCity())) {
      return [
        '#type' => 'markup',
        '#markup' => $this->t('Please enter your API key and City in the Admin panel to see the weather'),
      ];
    }

    try {
      if ($cache = $this->cacheBackend->get($cid)) {
        $data = $cache->data;
      }
      else {
        $response = $client->get('http://api.openweathermap.org/data/2.5/weather?q=' . $this->getCity() . ',&appid=' . $api_key . '&units=metric');
        $response_data = $response->getBody();
        $data = json_decode($response_data);
        $this->cacheBackend->set($cid, $data, $this->time->getRequestTime() + 21600);
      }

      $build = [
        '#theme' => 'weather_block',
        '#data' => $data,
        '#attached' => [
          'library' => [
            'sydneypro_weather/sydneypro_weather',
          ],
        ],
      ];

      return $build;

    }
  // ....

Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Разработка Drupal и AngularJS: Идеальное сочетание для вашей веб-стратегии
Разработка Drupal и AngularJS: Идеальное сочетание для вашей веб-стратегии
Один опытный веб-разработчик назвал комбинацию Drupal и AngularJS "сочетанием, созданным на небесах". Почему так? Потому что вместе они могут создать...
1
0
18
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вам нужно отобразить некоторые данные в соответствии с заданным городом, поэтому вы должны кэшировать данные для каждого города, используя идентификатор кэша, который позволяет вам получать данные для определенного города. Другими словами, $cid должен содержать название или идентификатор города.

    $city = $this->getCity();
    $cid = 'sydneypro_weather:' . $city;
    
  2. Использование переменной для $city предотвращает двойной вызов getCity(). Также вы можете установить кеш, который сопоставляет IP-адреса с соответствующим им городом, но это может быть не очень хорошей идеей, поскольку количество (возможных) различных адресов, заполняющих таблицу кеша, может быть очень большим.
    Другой подход заключается в том, чтобы получить регион/город пользователя из его браузера с помощью javascript и/или файлов cookie и вызывать API только для тех, кто не делится своим местоположением.

Другие вопросы по теме