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);