我在 PHP 上犯了价值 646 美元的错误
昨天,我在使用 Google Places API(Web 服务)迭代 while 循环时,学到了非常宝贵的一课,这花了我 646 美元。没错,我在一小时内 ping 了 Places API 17,000 次 😳 🤦🏻♂️。所以我决定今天写一篇文章,记录我的错误,希望能防止其他人遇到同样的问题。让我们深入探讨一下。
发生了什么?
嗯……我目前正在开发一个使用 Google Places API 的 Web 和移动应用程序,我需要使用附近搜索返回结果。Google API 只返回 20 条结果,最多 60 条,您可以使用他们的分页功能获取。所以,让我们分析一下代码,解释一下哪里出了问题。
// This is the initial request that we send to get the initial 20 results.
$response = Http::get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=' . $request->lat .'%2C'. $request->lng.'&radius='.$request->radius.'&type=restaurant&key=' . env('GOOGLE_MAP_KEY'))->json();
// We push those results to our google_places collection
$this->google_places->push(...$response['results']);
// Here we check the status of the response, if it's ok we continue.
if ($response['status'] == 'OK') {
// If the response has a next page token we loop through until it doesn't, getting the next 20 results.
while ($response['next_page_token']) {
// The google places api has a delay from when the next_page_token is created and those results are actually available.
// So we need to create a delay before we try and grab the next results otherwise we will get an INVALID_REQUEST response.
sleep(2);
// Now we get the next 20 results.
$new_results = Http::get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?pagetoken=' . $response['next_page_token'] . '&key=' . env('GOOGLE_MAP_KEY'))->json();
// Then we push those results to our collection.
$this->google_places->push(...$new_results['results']);
}
}
你能找出我哪里出错了吗?PHP 中的 while 循环会一直运行,直到返回 false,而我传入 while 循环的值总是返回 true,因此 while 循环进入了无限循环。我使用的是$response['next_page_token']
初始请求中的,它总是返回 true。
我该如何解决这个问题?
$response = Http::get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=' . $request->lat .'%2C'. $request->lng.'&radius='.$request->radius.'&type=restaurant&key=' . env('GOOGLE_MAP_KEY'))->json();
$this->google_places->push(...$response['results']);
// We check to see if the above response includes the key next_page_token, if it does we set the next_page_token property to true
// This is super important, this is how we're going to ensure our loop doesn't run infinitely.
if (array_key_exists('next_page_token', $response)) {
$this->next_page_token = true;
}
if ($response['status'] == 'OK') {
// For the while loop we check to see if the next_page_token is true, it will end when it returns false.
while ($this->next_page_token) {
sleep(2);
$new_results = Http::get('https://maps.googleapis.com/maps/api/place/nearbysearch/json?pagetoken=' . $response['next_page_token'] . '&key=' . env('GOOGLE_MAP_KEY'))->json();
$this->google_places->push(...$new_results['results']);
// This is also super important, here we check to see if next_page_token does not exist or if we're getting an invalid request response.
// If we do we want to set the next_page_token to false so that the loop ends.
if (!array_key_exists('next_page_token', $new_results) || $new_results['status'] == 'INVALID_REQUEST') {
$this->next_page_token = false;
}
}
}
// Being that the Google API only returns 60 results that means the loop should only have to run a max of 2 times.
// So you could create a $count variable and add that like so while($this->next_page_token || $count <= 2) and increment the count each time.
// This will act as a safety in case you accidentally throw a forever truthy statement in there like I did.
结论:
在使用收费 API 并在循环中运行时务必谨慎。为了安全起见,您可以创建一个 $count 变量,并在达到设定的计数时停止循环,以防万一出错。我接下来会这样做,以确保不再犯同样的错误。希望这篇文章能帮助您或其他人避免犯同样的错误。✌🏻