Рекурсивный вызов до тех пор, пока значение не будет больше ответа

У меня есть вызов cURL этим services/data/v28.0/query/?q=SELECT Id,Name,LastModifiedDate FROM Territory и ответ выглядит так:

 { "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 и так далее.

Я должен вызывать nextRecordsUrl 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: Потеря значений на 1-й итерации

Я обновил свой код:

 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 итерации time 1 я получаю эту ошибку:

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

Почему это?

Related of "Рекурсивный вызов до тех пор, пока значение не будет больше ответа"

Вы можете использовать цикл while с булевой переменной. Как только полученный вами ответ является последним (свойство donetrue ), измените значение этой логической переменной, и цикл должен остановиться.

 <?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; } } в <?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; } } 

Что касается вашего обновления: хотя я не думаю, что вы должны использовать рекурсивные методы для этой проблемы, просто добавьте данные, которые вы хотите сохранить в качестве ссылки на функцию, и используйте 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?