递归函数直到完成值为真并将每个响应合并为一个大响应
Recursive function until done value is true and merge each response into a big one
我有这个功能:
public function syncTerritoriesSOQLQuery($veevaToken, $instanceUrl, $tokenUrl)
{
$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);
$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);
$soqlObj2 = json_decode($jsonResponse, true);
return $soqlObj2;
}
当我调用它时,我得到了这样的回复:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000",
"records": [ ... ]
}
这意味着完整的记录集将有 6911 个项目,但在第一次请求时只有前 2000 个是 return,因为它是分页的。所以我需要一次又一次地调用相同的代码,直到 "done": true
。在每个新请求中,我需要通过在每次调用时附加值 return 来更改 $soqlUrl2
。例如:
1st time:
$soqlUrl2 = $instanceUrl.'/services/data/v28.0/query/?q='.urlencode($soqlQuery2);
2nd time:
$soqlUrl2 = $instanceUrl."/services/data/v28.0/query/01g8000002eI8dMAAS-2000";
3rd time:
$soqlUrl2 = $instanceUrl."/services/data/v28.0/query/01g8000002eI8dMAAS-4000";
...
直到 done
得到 true
的响应。我还应该将每次迭代的整个 JSON 结果合并为一个大结果,可以说:第二次的结果应该与第一次调用的结果合并,意思是 $soqlObj2
第 3 次的结果应该与伪代码中的先前合并:
merge($soqlObj2, 1st, 2nd, 3rd, ...)
我一直在研究这个功能:
public function performPaginateSOQLQuery($veevaToken, $instanceUrl, $tokenUrl, $nextRecordsUrl, &$dataToSave = array()) {
if ($nextRecordsUrl !== null && $nextRecordsUrl !== "") {
$keepRequesting = true;
while($keepRequesting){
$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);
$dataToSave[] = $nextRecordsUrlObj;
echo "iteration 2", "\n";
echo "url: ", $nextRecordsUrl, "\n";
echo "done: ";
var_dump($nextRecordsUrlObj['done']);
echo "\n";
if($nextRecordsUrlObj['done'] === true) {
$keepRequesting = false;
}
}
return array('url' => $nextRecordsUrlObj, 'data' => $dataToSave);
}
}
我从上面的函数 syncTerritoriesSOQLQuery()
调用它如下:
$entireSoqlObj2 = $this->performPaginateSOQLQuery(
$veevaToken,
$instanceUrl,
$tokenUrl,
$soqlObj2['nextRecordsUrl']
);
但它不起作用,因为我得到了这个结果:
iteration 0
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
正确的输出应该是这样的:
// 1st
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
// 2st
url: /services/data/v28.0/query/01g8000002eYb8LAAS-4000
done: bool(false)
// 3rd
url: /services/data/v28.0/query/01g8000002eYb8LAAS-6000
done: bool(true)
因为totalSize
是6911,有什么可以帮我修改密码的吗?我的错误在哪里?
注意: 我今天早些时候问 但我一点也不清楚所以我打开了一个包含更多信息的新问题。
你的递归函数中应该有 $soqlObj2['nextRecordsUrl']
,每次都应该用 $nextRecordsUrl
更新。现在它总是只检查第一页,因此你得到第二页的 url。
另外,我不明白你为什么在 performPaginateSOQLQuery()
中有这么多代码,你只是想遍历 syncTerritoriesSOQLQuery()
直到 done
,对吗?
更新:
正在更新您的 syncTerritoriesSOQLQuery()
以遍历所有页面。在我进行更改的所有地方添加评论。希望对您有所帮助。
<?php
public function syncTerritoriesSOQLQuery($veevaToken, $instanceUrl, $tokenUrl)
{
$soqlQuery2 = "SELECT Id,Name,LastModifiedDate FROM Territory";
// removed $instanceUrl, we'll add that inside while loop
$instancePath = '/services/data/v28.0/query/?q='.urlencode($soqlQuery2);
$final_output = array(); // all output will be appended to this array
$done = False; // we set this variable to true, once `done` is true
while( !$done ) {
$soqlUrl2 = $instanceUrl . $instancePath;
$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);
$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);
$soqlObj2 = json_decode($jsonResponse, true);
// here, we change the $instancePath to nextRecordsUrl
$instancePath = $soqlObj2['nextRecordsUrl'];
// set $done variable
$done = $soqlObj2['done'];
// appending the data obtained to $final_output array, you can change this string if u need.
$final_output[] = $soqlObj2;
}
return $final_output;
}
我有这个功能:
public function syncTerritoriesSOQLQuery($veevaToken, $instanceUrl, $tokenUrl)
{
$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);
$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);
$soqlObj2 = json_decode($jsonResponse, true);
return $soqlObj2;
}
当我调用它时,我得到了这样的回复:
{
"totalSize": 6911,
"done": false,
"nextRecordsUrl": "/services/data/v28.0/query/01g8000002eI8dMAAS-2000",
"records": [ ... ]
}
这意味着完整的记录集将有 6911 个项目,但在第一次请求时只有前 2000 个是 return,因为它是分页的。所以我需要一次又一次地调用相同的代码,直到 "done": true
。在每个新请求中,我需要通过在每次调用时附加值 return 来更改 $soqlUrl2
。例如:
1st time:
$soqlUrl2 = $instanceUrl.'/services/data/v28.0/query/?q='.urlencode($soqlQuery2);
2nd time:
$soqlUrl2 = $instanceUrl."/services/data/v28.0/query/01g8000002eI8dMAAS-2000";
3rd time:
$soqlUrl2 = $instanceUrl."/services/data/v28.0/query/01g8000002eI8dMAAS-4000";
...
直到 done
得到 true
的响应。我还应该将每次迭代的整个 JSON 结果合并为一个大结果,可以说:第二次的结果应该与第一次调用的结果合并,意思是 $soqlObj2
第 3 次的结果应该与伪代码中的先前合并:
merge($soqlObj2, 1st, 2nd, 3rd, ...)
我一直在研究这个功能:
public function performPaginateSOQLQuery($veevaToken, $instanceUrl, $tokenUrl, $nextRecordsUrl, &$dataToSave = array()) {
if ($nextRecordsUrl !== null && $nextRecordsUrl !== "") {
$keepRequesting = true;
while($keepRequesting){
$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);
$dataToSave[] = $nextRecordsUrlObj;
echo "iteration 2", "\n";
echo "url: ", $nextRecordsUrl, "\n";
echo "done: ";
var_dump($nextRecordsUrlObj['done']);
echo "\n";
if($nextRecordsUrlObj['done'] === true) {
$keepRequesting = false;
}
}
return array('url' => $nextRecordsUrlObj, 'data' => $dataToSave);
}
}
我从上面的函数 syncTerritoriesSOQLQuery()
调用它如下:
$entireSoqlObj2 = $this->performPaginateSOQLQuery(
$veevaToken,
$instanceUrl,
$tokenUrl,
$soqlObj2['nextRecordsUrl']
);
但它不起作用,因为我得到了这个结果:
iteration 0
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
iteration 2
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
正确的输出应该是这样的:
// 1st
url: /services/data/v28.0/query/01g8000002eYb8LAAS-2000
done: bool(false)
// 2st
url: /services/data/v28.0/query/01g8000002eYb8LAAS-4000
done: bool(false)
// 3rd
url: /services/data/v28.0/query/01g8000002eYb8LAAS-6000
done: bool(true)
因为totalSize
是6911,有什么可以帮我修改密码的吗?我的错误在哪里?
注意: 我今天早些时候问
你的递归函数中应该有 $soqlObj2['nextRecordsUrl']
,每次都应该用 $nextRecordsUrl
更新。现在它总是只检查第一页,因此你得到第二页的 url。
另外,我不明白你为什么在 performPaginateSOQLQuery()
中有这么多代码,你只是想遍历 syncTerritoriesSOQLQuery()
直到 done
,对吗?
更新:
正在更新您的 syncTerritoriesSOQLQuery()
以遍历所有页面。在我进行更改的所有地方添加评论。希望对您有所帮助。
<?php
public function syncTerritoriesSOQLQuery($veevaToken, $instanceUrl, $tokenUrl)
{
$soqlQuery2 = "SELECT Id,Name,LastModifiedDate FROM Territory";
// removed $instanceUrl, we'll add that inside while loop
$instancePath = '/services/data/v28.0/query/?q='.urlencode($soqlQuery2);
$final_output = array(); // all output will be appended to this array
$done = False; // we set this variable to true, once `done` is true
while( !$done ) {
$soqlUrl2 = $instanceUrl . $instancePath;
$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);
$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);
$soqlObj2 = json_decode($jsonResponse, true);
// here, we change the $instancePath to nextRecordsUrl
$instancePath = $soqlObj2['nextRecordsUrl'];
// set $done variable
$done = $soqlObj2['done'];
// appending the data obtained to $final_output array, you can change this string if u need.
$final_output[] = $soqlObj2;
}
return $final_output;
}