我对此services/data/v28.0/query/?q=SELECT Id,Name,LastModifiedDate FROM Territory
进行了cURL调用,响应如下:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000",
"records": [ ... ]
}
这意味着完整的记录集将有6911个项目但是在第一个请求时只返回第一个2000,现在如果我将cURL调用更改为此/services/data/v28.0/query/01g8000002eI8dMAAS-2000
我将获得第一个2000个项目6911等等。
我应该递归cURL直到done = true
或nextRecordsUrl
为NULL
或者在回复中不再存在,怎么样?我需要一些建议或伪代码来说明如何实现这一点,因为我有点被困。
这显示了我应该执行的完整的递归调用集(这可能是动态的,因此硬代码不起作用):
call:
/services/data/v28.0/query/?q=SELECT Id,Name,LastModifiedDate FROM Territory
response:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000",
"records": [ ... ]
}
call:
/services/data/v28.0/query/01g8000002eI8dMAAS-2000
response:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-4000",
"records": [ ... ]
}
call:
/services/data/v28.0/query/01g8000002eI8dMAAS-4000
response:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-6000",
"records": [ ... ]
}
call:
/services/data/v28.0/query/01g8000002eI8dMAAS-6000
response:
{
"totalSize": 6911,
"done": true,
"records": [ ... ]
}
更新
我已经或多或少想出了如何实现这一点,但现在我的问题是如何合并递归每个响应的值。请参阅以下代码:
$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
来电的每次迭代中合并整个$nextRecordsUrlObj
和performPaginateSOQLQuery()
,怎么样?有什么帮助吗?
更新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);
}
}
但是在迭代time 1
上我收到了这个错误:
[Symfony\Component\Debug\Exception\ContextErrorException]
Notice: Undefined index: nextRecordsUrl
为什么?
答案 0 :(得分:1)
您可以使用带有布尔变量的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;
}
}
关于您的更新:
虽然我不认为你应该使用递归方法来解决这个问题,
只需将要“保存”as a reference的数据添加到该函数中,然后使用array_merge
即可。这样的事情:
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);
问题是你应该退货,否则会丢失。 您必须稍微更改一下这个功能,以便返回您想要的URL和数据。
也许这篇文章可以帮到你: php recursion global variable?