Php 递归调用,直到值不在响应上

Php 递归调用,直到值不在响应上,php,curl,recursion,Php,Curl,Recursion,我对这个services/data/v28.0/query/?q=从Territory中选择Id、名称、LastModifiedDate进行了cURL调用,响应如下所示: { "totalSize": 6911, "done": false, "nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000", "records": [ ... ] } 这意味着完整的记录集将有6911项,但在第一次请求时

我对这个
services/data/v28.0/query/?q=从Territory
中选择Id、名称、LastModifiedDate进行了cURL调用,响应如下所示:

{
  "totalSize": 6911,
  "done": false,
  "nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000",
  "records": [ ... ]
}
这意味着完整的记录集将有6911项,但在第一次请求时,只返回第一个2000项,现在如果我将cURL调用稍微更改为this
/services/data/v28.0/query/01g8000002eI8dMAAS-2000
我将获得第一个6911的下一个2000项,依此类推

我应该调用cURL recursive,直到
done=true
nextRecordsUrl
NULL
或响应中不再存在,如何?我需要一些建议或伪代码来说明如何实现这一点,因为我有点结巴

这显示了我应该执行的一整套递归调用(这可能是动态的,因此硬代码无法工作):

更新

我或多或少已经知道了如何实现这一点,但现在我的问题是如何合并每个响应的递归值。见下面的代码:

$soqlQuery2 = "SELECT Id,Name,LastModifiedDate FROM Territory";
$soqlUrl2 = $instanceUrl.'/services/data/v28.0/query/?q='.urlencode($soqlQuery2);

$curl = curl_init($soqlUrl2);

curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $veevaToken"));

$jsonResponse = curl_exec($curl);

curl_close($curl);

$soqlObj2 = json_decode($jsonResponse, true);

$this->performPaginateSOQLQuery($veevaToken, $instanceUrl, $tokenUrl, $soqlObj2['nextRecordsUrl']);
在上面的
$soqlObj2['done']
$soqlObj2['nextRecordsUrl']
中,我将获得第二次调用和递归调用所需的值。因此,我构建了这个函数:

public function performPaginateSOQLQuery($veevaToken, $instanceUrl, $tokenUrl, $nextRecordsUrl)
{
    if (isset($nextRecordsUrl) && $nextRecordsUrl !== null && $nextRecordsUrl !== "") {
        $nextRecordsUrlSOQLQuery = $instanceUrl.$nextRecordsUrl;

        $curl = curl_init($nextRecordsUrlSOQLQuery);

        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $veevaToken"));

        $jsonResponse = curl_exec($curl);

        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if ($status != 200) {
            $respObj['error'] = "Error: call to token URL $tokenUrl failed with status $status, response $jsonResponse, curl_error ".curl_error(
                    $curl
                ).", curl_errno ".curl_errno($curl);

            return $respObj;
        }

        curl_close($curl);

        $nextRecordsUrlObj = json_decode($jsonResponse, true);

        while ($nextRecordsUrlObj['done'] !== true) {
            $this->performPaginateSOQLQuery($veevaToken, $instanceUrl ,$tokenUrl, $nextRecordsUrlObj['nextRecordsUrl']);
        }

        return $nextRecordsUrlObj;
    }
}
但是我需要将整个
$soqlObj2
performPaginateSOQLQuery()
调用中每次迭代的
$nextRecordsUrlObj
合并,如何?有什么帮助吗

更新2:在第一次迭代中丢失值

我已将代码更新为:

public function performPaginateSOQLQuery(
    $veevaToken,
    $instanceUrl,
    $tokenUrl,
    &$nextRecordsUrl,
    &$dataToSave = array()
) {
    if (isset($nextRecordsUrl) && $nextRecordsUrl !== null && $nextRecordsUrl !== "") {
        $nextRecordsUrlSOQLQuery = $instanceUrl.$nextRecordsUrl;

        $curl = curl_init($nextRecordsUrlSOQLQuery);

        curl_setopt($curl, CURLOPT_HEADER, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Authorization: OAuth $veevaToken"));

        $jsonResponse = curl_exec($curl);

        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if ($status != 200) {
            $respObj['error'] = "Error: call to token URL $tokenUrl failed with status $status, response $jsonResponse, curl_error ".curl_error(
                    $curl
                ).", curl_errno ".curl_errno($curl);

            return $respObj;
        }

        curl_close($curl);

        $nextRecordsUrlObj = json_decode($jsonResponse, true);

        echo $nextRecordsUrlObj['nextRecordsUrl'] . "\n";
        print_r($nextRecordsUrlObj);

        $dataToSave[] = $nextRecordsUrlObj;

        $i = 0;
        while ($nextRecordsUrlObj['done'] !== true) {
            echo "time ".$i;
            $i++;
            $this->performPaginateSOQLQuery(
                $veevaToken,
                $instanceUrl,
                $tokenUrl,
                $nextRecordsUrlObj['nextRecordsUrl'],
                $dataToSave
            );
        }

        return array('url' => $nextRecordsUrlObj, 'data' => $dataToSave);
    }
}
但是在迭代
时间1
中,我得到了这个错误:

[Symfony\Component\Debug\Exception\ContextErrorException]
  Notice: Undefined index: nextRecordsUrl

这是为什么?

您可以使用带有布尔变量的
while
循环。 一旦得到的响应是最后一个响应(
done
属性为
true
),请更改该布尔变量的值,循环应停止

<?php

//Assuming $response contains the response you're getting
//and that it's JSON-encoded.

$keepRequesting = true;
while($keepRequesting){

  //Your curl code over here
  // ...

  $response = json_decode($response);
  if($response->done == true) {
     $keepRequesting = false;
  }

}
问题是你应该归还它,否则它会丢失的。 您必须稍微更改函数,以便它返回URL和所需的数据

也许这篇文章可以帮助你:

您好,在您回答我之前,我想我已经找到了实现这一点的方法,但我遇到了第二个问题,您能看看我的编辑吗?如果你能帮我的忙,我会投票同意你的答案,我不明白你的意思,你能改变一下我的函数吗?作为一个例子,为了得到你所说的吗?以我的编辑为主要例子:
$soqlObj2
$dataToSave
$nextRecordsUrlObj
$saved
?我没有得到那些变量应该被编辑的代码,因此它将只使用一个变量,还添加了函数调用的行为。还有两件事,
$saved
在返回语句上应该是
$dataToSave
对吗?打字错误?当我第一次以
$this->performPaginateSOQLQuery($veevaToken、$instanceUrl、$tokenUrl、$soqlObj2['nextRecordsUrl']);的形式调用该函数时,`
$dataToSave`将是完整的
$soqlObj2
对象吗?
<?php

//Assuming $response contains the response you're getting
//and that it's JSON-encoded.

$keepRequesting = true;
while($keepRequesting){

  //Your curl code over here
  // ...

  $response = json_decode($response);
  if($response->done == true) {
     $keepRequesting = false;
  }

}
public function performPaginateSOQLQuery($veevaToken, $instanceUrl, $tokenUrl, $nextRecordsUrl, &$dataToSave = array()) { //1 new parameters.
    //More code here...


    $nextRecordsUrlObj = json_decode($jsonResponse, true);
    $dataToSave[] = $nextRecordsUrlObj;
    while ($nextRecordsUrlObj['done'] !== true) {
        $this->performPaginateSOQLQuery($veevaToken, $instanceUrl ,$tokenUrl, $nextRecordsUrlObj['nextRecordsUrl'], $dataToSave);
    }

    return array('url' => $nextRecordsUrlObj, 'data' => $dataToSave);