没有为新用户显示所需的数据,因为数据是从以前用户的缓存中获取的
Not the required data is displayed for the new user, because the data is taken from the cache of the previous user
我制作了一个显示特定城市天气的自定义模块。
但是我在代码审查后得到了这些评论:
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;
}
// ....
您需要根据给定的城市显示一些数据,因此您应该在 per-city 的基础上缓存数据,使用允许您检索特定城市数据的缓存 id城市。换句话说,$cid
必须包含城市名称或标识符。
$city = $this->getCity();
$cid = 'sydneypro_weather:' . $city;
为 $city
使用变量可防止 getCity()
被调用两次。您也可以设置一个缓存,将 IP 地址映射到相应的城市,但这可能不是一个好主意,因为填充缓存的(可能的)不同地址的数量可能非常高 table。
另一种方法是使用 javascript and/or cookie 从他的浏览器获取用户的 region/city,并只为那些不共享其位置的用户调用 api。
我制作了一个显示特定城市天气的自定义模块。
但是我在代码审查后得到了这些评论:
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;
}
// ....
您需要根据给定的城市显示一些数据,因此您应该在 per-city 的基础上缓存数据,使用允许您检索特定城市数据的缓存 id城市。换句话说,
$cid
必须包含城市名称或标识符。$city = $this->getCity(); $cid = 'sydneypro_weather:' . $city;
为
$city
使用变量可防止getCity()
被调用两次。您也可以设置一个缓存,将 IP 地址映射到相应的城市,但这可能不是一个好主意,因为填充缓存的(可能的)不同地址的数量可能非常高 table。
另一种方法是使用 javascript and/or cookie 从他的浏览器获取用户的 region/city,并只为那些不共享其位置的用户调用 api。