对API的循环查询非常慢

时间:2017-03-19 22:19:29

标签: php json performance loops

我听说可以通过只使用一个查询来循环JSON数据,而不是对每个循环进行查询。有任何想法如何从这段代码中做到这一点? 我真的需要这样做,因为成功加载页面需要3分钟。

* PHP *

<?php foreach ($return as $user) {
    $link = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=$devkey&steamids=$user->SteamID";
    $json = file_get_contents($link);
    $decoding = json_decode($json);
    $avatar = $decoding->response->players[0]->avatar;
?>
<td id="addme"><img src="<?php echo $avatar; ?>" width="32" height="32"></td>
<td><?php echo $user->DisplayName; ?></td>
<td><?php echo $user->SteamID; ?>  <a href="http://steamcommunity.com/profiles/<?php echo $user->SteamID; ?>/" target="_blank"><span class="glyphicon glyphicon-new-window" id="gotosteamprofile"></span></a></td>
<td><?php
         $ipredc = substr($user->Address, 0, -6);
         echo $ipredc; ?></td>
<td><?php 
         $toconver = $user->ConnectedSeconds;
         $hours = floor($toconver / 3600);
         $mins = floor($toconver / 60 % 60);
         $secs = floor($toconver % 60);
         $timeFormat = sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
         echo $timeFormat;
      ?></td>
</tr>

<?php
}
?>

2 个答案:

答案 0 :(得分:0)

防止多次调用API的唯一方法是找到一个同义数据点。幸运的是,Steam提供了这样的观点。

根据 Steam API on GetPlayerSummaries ,您可以同时返回最多100名玩家的数据。因此,您只需要拨打一次(假设您只是抓取一些玩家的数据)。

foreach ($return as $user)内,您当前正在将$user传递给查询本身:

&steamids=$user->SteamID

这充当GET参数,并调用多个网址:

/GetPlayerSummaries/v0002/?key=$devkey&steamids=12345678
/GetPlayerSummaries/v0002/?key=$devkey&steamids=23456789

这显然非常昂贵,但幸运的是,您可以使用Comma-delimited list of 64 bit Steam IDs to return profile information for一次性传递所有ID。因此,您应该将此列表创建为变量以立即发送所有内容:

$combined_ids = '';
foreach ($return as $user) {
  $combined_ids.= $user->SteamID . ',';
}
// $combined_ids = '1,2,3,4,5';

然后,您可以将此变量传递到循环的外部查询中

$link = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=$devkey&steamids=$combined_ids";
$json = file_get_contents($link);
$decoding = json_decode($json);

最后, 单次调用API之后,您将通过每个用户的结果执行次要循环,并使用预定义的{{1变量。

$decoding

请注意,您可能需要根据API同时处理多个用户的回报来调整结果,而不是一次调整一次。

希望这有帮助! :)

答案 1 :(得分:0)

根据文档,您可以传递逗号分隔的最多100个ID字符串。

  

以逗号分隔的64位Steam ID列表,用于返回个人资料信息。最多可以请求100个Steam ID enter link description here

因此,基于我的评论的答案,您可以这样做:

$allRows = []; // initialize all rows array

// organize the database result into an array as such
$allSteamUsers = [
    '76561197989628222'=>['Address'=>'Some Address 1','DisplayName'=>'Some Name'], // => some data
    '76561197989628233'=>['Address'=>'Some Address 2','DisplayName'=>'Some Name'], // => some data
    '76561197989628444'=>['Address'=>'Some Address 3','DisplayName'=>'Some Name'], // => some data
    // .......
    '76561197989628447'=>['Address'=>'Some Address 298','DisplayName'=>'Some Name'], // => some data
    '76561197989628448'=>['Address'=>'Some Address 299','DisplayName'=>'Some Name'], // => some data
    '76561197989628449'=>['Address'=>'Some Address 300','DisplayName'=>'Some Name'], // => some data
];

// chunk the user array into parts of 100 and preserve keys
$steamUsersChunks = array_chunk($allSteamUsers, 100, true);

// loop parts
foreach($steamUsersChunks as $steamUsers){

    // build the comma separated id string for the query
    $steam_ids_str = implode(',',array_keys($steamUsers));

    $url = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key=$devkey&steamids=$steam_ids_str";
    $items = json_decode(file_get_contents($url),true); // get JSON and decode with associative array flag set to true
    $players = $items['response']['players']; // get the players array

    $rows = [];

    // loop players array
    foreach($players as $item) {

        // set your variables
        $steamId = $item['steamid'];
        $avatar = $item['avatar'];
        $user_displayName = $steamUsers[$steamId]['DisplayName'];
        $user_Address = $steamUsers[$steamId]['Address'];
        $ipredc = substr($user_Address, 0, -6);

        // build row and add to rows container of this players loop
        $rows[] = '<tr>
        <td id="addme"><img src="'.$avatar.'" width="32" height="32"></td>
        <td>'.$user_displayName.'</td>
        <td>'.$steamId.'  <a href="http://steamcommunity.com/profiles/'.$steamId.'/" target="_blank"><span class="glyphicon glyphicon-new-window" id="gotosteamprofile"></span></a></td>
        <td>'.$ipredc.'</td>
        <td></td>
        </tr>';

    }

    // attach to the general table
    $allRows[] = implode("\n",$rows);

}

// display rows where ever needed
echo implode("\n",$allRows);