我在 PHP 上犯了价值 646 美元的错误

2025-06-09

我在 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']);
            }
        }


Enter fullscreen mode Exit fullscreen mode

你能找出我哪里出错了吗?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.


Enter fullscreen mode Exit fullscreen mode

Google Places API 图表

Google Places API 计费

结论:
在使用收费 API 并在循环中运行时务必谨慎。为了安全起见,您可以创建一个 $count 变量,并在达到设定的计数时停止循环,以防万一出错。我接下来会这样做,以确保不再犯同样的错误。希望这篇文章能帮助您或其他人避免犯同样的错误。✌🏻

鏂囩珷鏉ユ簮锛�https://dev.to/jringeisen/my-646-mistake-with-php-4l9d
PREV
让我们超越 console.log 语句。(console 对象远比我们肉眼所能看到的要复杂得多。)不同类型的日志记录。console.assert() console.count, console.countReset console.time(), console.timeEnd() console.group(), console.groupEnd() console.table() console.trace() 格式化输出
NEXT
如何使 Vim 成为 Python IDE - 最佳 Python IDE。