将两个分离的API调用值放入一个数组中

6

情况

我有两个API调用,一个是获取所有设备的调用,另一个是获取所有组的调用。我想要实现的目标是有一个调用能够获取到包含该组设备的组。

这是获取设备的函数:

public function getAll($environment, $options)
{
    // Get group ids from database, used for pairing groups with environments
    $groups = Device::where('source_id', $options['deviceSourceId'])->get();
    $groupIds = [];
    foreach ($groups as $group) {
        $groupIds[] = $group['group_id'];
    }

    // Parameters
    $apiparams = [
        'headers' => $this->getHeaders($environment)
    ];

    $devices = [];

    foreach($groupIds as $groupId)
    {
        $responseAPI = $this->getClient()->request('GET', 'devices?groupid=' . $groupId, $apiparams);
        $responseAPI = json_decode($responseAPI->getBody()->getContents(), true);
        $devices[] = $responseAPI['devices'];
    }

    return $devices;
}

这是获取组的功能

public function getGroups($environment, $options)
{
    // Get group ids from database, used for pairing groups with environments
    $groups = Device::where('source_id', $options['deviceSourceId'])->get();
    $groupIds = [];
    foreach ($groups as $group) {
        $groupIds[] = $group['group_id'];
    }

    // Parameters
    $apiparams = [
        'headers' => $this->getHeaders($environment)
    ];

    $groups2 = [];

    foreach($groupIds as $groupId)
    {
        $responseAPI = $this->getClient()->request('GET', 'groups/' . $groupId, $apiparams);
        $responseAPI = json_decode($responseAPI->getBody()->getContents(), true);

        $groups2[] = $responseAPI;
    }
    return $groups2;
}

当前响应

这是我从这些中获取的响应。

// Device response
[
    {
        "remotecontrol_id": "r5674567"
        "device_id": "d871212",
        "alias": "PC-01",
        "groupid": "g9873491",
        "online_state": "Online",
        "assigned_to": false
    },
    {
        "remotecontrol_id": "r8370129"
        "device_id": "d091231",
        "alias": "PC-02",
        "groupid": "g9873491",
        "online_state": "Offline",
        "assigned_to": false
    }
]

// Group response
{
    "id": "g9873491"
    "name": "companyname",
    "permissions": "owned"
}

所需回复

我希望得到的回复是:

[{id: "g9873491",
  name: "companyname",
  devices: [{device_id: "d871212",
             alias: "PC-01",
             online_state: "Online"},
            {device_id: "d091231",
             alias: "PC-02",
             online_state: "Offline"}
            }],
}]

我需要怎么做?

Sevavietl编辑

public function getAll($environment, $options)
{
    // Get group ids from database, used for pairing groups with environments
    $groups = Device::where('source_id', $options['deviceSourceId'])->get();
    $groupIds = [];
    foreach ($groups as $group) {
        $groupIds[] = $group['group_id'];
    }

    // Parameters
    $apiparams = [
        'headers' => $this->getHeaders($environment)
    ];

    foreach($groupIds as $groupId)
    {

        $responseAPI1 = $this->getClient()->request('GET', 'groups/' . $groupId, $apiparams);
        $responseAPI2 = $this->getClient()->request('GET', 'devices?groupid=' . $groupId, $apiparams);

        $groups2 = json_decode($responseAPI1->getBody()->getContents(), true);
        $devices = json_decode($responseAPI2->getBody()->getContents(), true);

        $result = array_values(array_reduce(
            $devices,
            function ($carry, $device) {
                if (isset($carry[$device['groupid']])) { // Undefined index: groupid
                    // Add device to group.
                    $carry[$device['groupid']]['devices'][] = [
                        'device_id' => $device['device_id'],
                        'alias' => $device['alias'],
                        'online_state' => $device['online_state']
                    ];
                }

                return $carry;
            },
            // Reindex groups by id.
            array_column($groups2, null, 'id')
        ));
    }

    return $result;
}

1
请问能否以文本格式回复,而不是图片呢?这样会稍微容易一些。如果数据比较敏感,是否可以加入一些虚假数据,以便我们看到实际匹配情况?同时,提供一个带有虚假数据的 API 调用示例,将会更有助于理解所需的响应。 - IsThisJavascript
1
@IsThisJavascript 当然,我会编辑这篇文章! - idontunderstandarrays
@IsThisJavascript 当然,我会做的!马上回来。 - idontunderstandarrays
@IsThisJavascript 帖子已经编辑过了,希望现在清晰明了。 - idontunderstandarrays
@idontunderstandarrays 抱歉,我现在还有几个会议,还没有时间看它。 - IsThisJavascript
显示剩余6条评论
1个回答

1
如果您无法控制API,则无法减少调用次数,因为您只能使用API本身定义的调用。因此,一种解决方案是自己准备所需格式的响应。您可以执行以下操作:
$devices = json_decode($devices, true);
$groups = json_decode($groups, true);

$result = array_values(array_reduce(
    $devices,
    function ($carry, $device) {
        if (isset($carry[$device['groupid']])) {
            // Add device to group.
            $carry[$device['groupid']]['devices'][] = [
                'device_id' => $device['device_id'],
                'alias' => $device['alias'],
                'online_state' => $device['online_state']
            ];
        }

        return $carry;
    },
    // Reindex groups by id.
    array_column($groups, null, 'id')
));

这里是演示
由于您正在使用 Laravel,另一种方法是利用 Laravel 集合。但在这种特定情况下,我猜除非您是集合大师(并且已经从头到尾阅读了 "重构到集合" :)),否则普通的 PHP 数组函数更容易理解和处理。

我在If语句处收到了一个未定义索引错误(在该行添加了一条注释)。你能看一下吗? - idontunderstandarrays
@idontunderstandarrays,组的ID必须位于另一个索引下。可能是“group_id”或类似的东西。 - sevavietl
仍然是一样的,尝试了所有可能性。这是我收到的错误响应:'Undefined index: group_id', '/var/www/extensions/Teamviewer/API/Services/TeamviewerLocal.php', '111', array('carry' => array('g121012823', 'companyname', 'owned'), 'device' => array(array('remotecontrol_id' => 'r691200188', 'device_id' => 'd647244096', 'alias' => 'PC-01', 'groupid' => 'g547621523', 'online_state' => 'Online', 'assigned_to' => false)。它确实有一个groupid对吧? - idontunderstandarrays
@idontunderstandarrays,对我来说更难的是猜测所有可能性,因为我无法看到API的实际输出。我认为你不应该尝试所有可能性,而是在if块之前执行var_dump($device)以查看它的样子。这可能会给你一些提示,告诉你哪里出了问题。 - sevavietl
@idontunderstandarrays,抱歉,以这种格式很难帮助你。我认为我的答案应该给你基本的思路。尝试调试并找出为什么数组中没有这样的偏移量。也许有些设备不属于任何组。正如您从演示中看到的那样,代码适用于您在问题中提供的数据格式。因此,您应该弄清楚为什么实际数据不遵循该格式。 - sevavietl
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接