Loop through API response with pagination - php

I'm making an api call that return only 100 records:
$response = $api->order->{"events"}->get();
To get next 100 records I have to call api with last ID from response, for example:
$response = $api->order->{"events?from=LAST_ID"}->get();
So how to make iteration to get all records?

I had a similar task in different projects, and I use a while() iteration. It might not be the cleanest solution, but it gets the job done.
$response = $api->order->{"events"}->get();
while ( $response->count > 0 ) :
// Do something with $response
$response = $api->order->{"events?from=LAST_ID"}->get();
endwhile;

Related

ZohoCRM Module getRecords PHP

I'm using the ZohoCRM PHP SDK to attempt to pull all Account records from the CRM and manipulate them locally (do some reports). The basic code looks like this, which works fine:
$account_module = ZCRMModule::getInstance('Accounts');
$response = $account_module->getRecords();
$records = $response->getData();
foreach ($records as $record) {
// do stuff
}
The problem is that the $records object only has 200 records (out of about 3000 total). I can't find any docs in the (minimally / poorly documented) SDK documentation showing how to paginate or get bigger result sets, and the Zoho code samples in the dev site don't seem to be using the same SDK for some reason.
Does anyone know how I can paginate through these records?
The getRecords() method seems to accept 2 parameters. This is used within some of their examples. You should be able to use those params to set/control pagination.
$param_map = ["page" => "20", "per_page" => "200"];
$response = $account_module->getRecords($param_map);
#dakdad was right that you can pass in the page and per page values into the param_map. You also should use the $response->getInfo()->getMoreRecords() to determine if you need to paginate. Something like this seems to work:
$account_module = ZCRMModule::getInstance('Accounts');
$page = 1;
$has_more = true;
while ($has_more) {
$param_map = ["page" => $page, "per_page" => "200"];
$response = $account_module->getRecords($param_map);
$has_more = $response->getInfo()->getMoreRecords();
$records = $response->getData();
foreach ($records as $record) {
// do stuff
}
$page++;
}

Push Request from a Do while using Guzzle

I have a problem with my results array, what I initially intended to have is something like this
$promises = [
'0' => $client->getAsync("www.api.com/opportunities?api=key&page=1fields=['fields']"),
'1' => $client->getAsync("www.api.com/opportunities?api=key&page=2fields=['fields']"),
'2' => $client->getAsync("www.api.com/opportunities?api=key&page=3fields=['fields']")
];
An array of request promises, I will use it because I want to retrieve a collection of data from the API that I am using. This is what the API first page looks like
In my request I want to get page 2,3,4.
This is how page 2 looks like
I made a do while loop on my PHP script but it seems to run an infinite loop
This is how it should work. First I run the initial request then get totalRecordCount = 154 and subtract it to recordCount = 100 if difference is != 0 it run it again and change the $pageNumber and push it to the promises.
This is my function code.Here's my code
function runRequest(){
$promises = [];
$client = new \GuzzleHttp\Client();
$pageCounter = 1;
$globalCount = 0;
do {
//request first and then check if has difference
$url = 'https://api.com/opportunities_dates?key='.$GLOBALS['API_KEY'].'&page='.$pageCounter.'&fields=["fields"]';
$initialRequest = $client->getAsync($url);
$initialRequest->then(function ($response) {
return $response;
});
$initialResponse = $initialRequest->wait();
$initialBody = json_decode($initialResponse->getBody());
$totalRecordCount = $initialBody->totalRecordCount;//154
$recordCount = $initialBody->recordCount;//100
$difference = $totalRecordCount - $recordCount;//54
$pageCounter++;
$globalCount += $recordCount;
array_push($promises,$url);
} while ($totalRecordCount >= $globalCount);
return $promises;
}
$a = $runRequest();
print_r($a); //contains array of endpoint like in the sample above
There is an endless loop because you keep looping when the total record count equals the global count. Page 3 and above have 0 records, so the total will be 154. Replacing the >= with a > will solve the loop.
However, the code will still not work as you expect it to do. For each page, you prepare a request with getAsync() and immediately do a wait(). The then statement does nothing. It returns the response, which it already does by default. So in practice, these are all sync requests.
Given that the page size is constant, you can calculate the pages you need based on the information given on the first request.
function runRequest(){
$promises = [];
$client = new \GuzzleHttp\Client();
$url = 'https://api.com/opportunities_dates?key='.$GLOBALS['API_KEY'].'&fields=["fields"]';
// Initial request to get total record count and page count
$initialRequest = $client->getAsync($url.'&page=1');
$initialResponse = $initialRequest->wait();
$initialBody = json_decode($initialResponse->getBody());
$promises[] = $initialRequest;
$totalRecordCount = $initialBody->totalRecordCount;//154
$pageSize = $initialBody->pageSize;//100
$nrOfPages = ceil($totalRecordCount / $pageSize);//2
for ($page = 2; $page <= $nrOfPages; $page++) {
$promises[] = $client->getAsync($url.'&page='.$page);
}
return $promises;
}
$promises = runRequest();
$responses = \GuzzleHttp\Promise\unwrap($promises);
Note that the function now returns promises and not URLs as strings.
It doesn't matter that the first promise is already settled. The unwrap function will not cause another GET request for page 1, but return the existing response. For all other pages, the requests are done concurrently.

How to count JSON response and output how many lines there are

Hello fellow developers,
I have been trying to manipulate the output and display the total amount of workers there are instead of outputting the workers name as a string.
Bellow you will find the data that i am receiving and further down i will explain how i would like to handle the JSON response.
{
"result":
{
"addr":"ADDRESS_HERE",
"workers":
[
["worker1080",{},2,1,"200000",0,22],
["worker1080",{"a":"899.4"},3,1,"512",0,24]
],
"algo":-1
},
"method":"stats.provider.workers"
}
So basically as you can see from the above response that there are 2 workers named "worker1080" active on that address.
The bellow php code is how i retrieve the data and output only the names of the workers:
<?php
$btcwallet = get_btc_addy();
if (isset($cur_addy)) {
$method4 = new methods();
$worker_stats = new urls();
$get_data = file_get_contents(utf8_encode($worker_stats->nice_url.$method4->m4.$cur_addy));
$get_json = json_decode($get_data, true);
foreach ($get_json['result']['workers'] as $v) {
$i = 0;
print $v[$i++]."<br />";
}
}
?>
$get_json is the variable that decodes the data from $get_data and displays the worker names and increments every time a worker is added or online.
now i currently have 2 workers online as shown in the JSON response.
it outputs:
worker1080
worker1080
which is perfect although if i try using a foreach statement and try to display the the total amount of workers online it should display 2 instead of the names, it has to also increment for each worker that the json repsonse outputs.
EG: i have 2 workers online now, but in an hour i will connect 10 more it would display the following:
worker1080
worker1080
worker1070
worker1070
worker1080ti
worker1080ti
workerASIC
workerASIC
workerASIC
workerCPU
workerCPU
workerCPU
Now i try to use the following to display the total:
count($v[$i++]);
and i have tried using a foreach within the foreach, and both count and the foreach both will either display "0" by all the workers or "1"
bellow is an example of the output.
0
0
0
0
0
How would i go about counting each line in the output and display the total number of workers ?
Thanks #symcbean for the solution.
<?php
$btcwallet = get_btc_addy();
if (isset($cur_addy)) {
$method4 = new methods();
$worker_stats = new urls();
$get_data = file_get_contents(utf8_encode($worker_stats->nice_url.$method4->m4.$cur_addy));
$get_json = json_decode($get_data, true);
print count($get_json['result']['workers'])."<br />"; // <-- solution *removed foreach and $i incrementation as its not needed for count
}
?>
it now displays the correct number of workers :)

for each loop with json data

I'm having a small problem while pulling tide data from the wunderground api. When I use the code below to pull the time of day for low tide I get an accurate answer one day, but a wrong answer the following day:
<?
$json_url = 'http://api.wunderground.com/api/b2b4a1ad0a889006/tide/q/NJ/Wildwood.json';
// jSON String for request
$json_string = '[http://api.wunderground.com/api/b2b4a1ad0a889006/tide/q/NJ/Wildwood.json]';
// Initializing curl
$ch = curl_init( $json_url );
// Configuring curl options
$options = array(
CURLOPT_RETURNTRANSFER => true,
);
// Setting curl options
curl_setopt_array( $ch, $options );
// Getting results
$result = curl_exec($ch); // Getting jSON result string
$parsed_json = json_decode($result);
$parsed_data->stats; //this returns
$low_tide_time = $parsed_json->tide->tideSummary[8]->date->pretty;
echo $low_tide_time;
?>
The reason for this is clear. The array key (in this case [8]) is not consistently assigned to the same tide data type (low tide) every day. So today [8] may be the array key associated with the time for low tide, but tomorrow [8] will be the array key assigned to sunrise, moonrise, etc.
Is there a way to use a for each loop to grab the time for low tide?
Thanks!
I check JSON format and it should works:
foreach( $parsed_json->tide->tideSummary AS $tideSummary ) {
if( $tideSummary->data->type == "Low Tide" ) {
$low_tide_time = $tideSummary->date->pretty;
echo $low_tide_time;
// you can end of foreach
break;
}
}
If there is something unique in the $parsed_json->tide->tideSummary Object which belongs to your requested information (like "Title: Low Tide") you could do a foreach loop and check if that value is present.
Like this
foreach ($parsed_json->tide->tideSummary AS $tideSummary) {
if ($tideSummary->title == "Low Tide") {
$LowTide = $tideSummary;
}
}
You can access the Low Tide data after that like this:
echo $LowTide->Date;
PS: Untested and no info about your JSON Format, if there is no unique information to identify Low Tide it could get tricky..

facebook api: count attendees for event (limit problem)

Okay normally I'm all fine about the facebook API but I'm having a problem which just keeps me wondering. (I think it's a bug (Check ticket http://bugs.developers.facebook.net/show_bug.cgi?id=13694) but I wanted to throw it here if somebody has an idea).
I'm usng the facebook PHP library to count all attendees for a specific event
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending');
this works without a problem it correctly returns an array with all attendees...
now heres the problem:
This event has about 18.000 attendees right now.
The api call returns a max number of 992 attendees (and not 18000 as it should).
I tried
$attending = $facebook->api('/'.$fbparams['eventId'].'/attending?limit=20000');
for testing but it doesn't change anything.
So my actual question is:
If I can't get it to work by using the graph api what would be a good alternative? (Parsing the html of the event page maybe?) Right now I'm changing the value by hand every few hours which is tedious and unnecessary.
Actually there are two parameters, limit and offset. I think that you will have to play with both and continue making calls until one returns less than the max. limit.
Something like this, but in a recursive approach (I'm writting pseudo-code):
offset = 0;
maxLimit = 992;
totalAttendees = count(result)
if (totalAttendees >= maxLimit)
{
// do your stuff with each attendee
offset += totalAttendees;
// make a new call with the updated offset
// and check again
}
I've searched a lot and this is how I fixed it:
The requested URL should look something like this.
Here is where you can test it and here is the code I used:
function events_get_facebook_data($event_id) {
if (!$event_id) {
return false;
}
$token = klicango_friends_facebook_token();
if ($token) {
$parameters['access_token'] = $token;
$parameters['fields']= 'attending_count,invited_count';
$graph_url = url('https://graph.facebook.com/v2.2/' . $event_id , array('absolute' => TRUE, 'query' => $parameters));
$graph_result = drupal_http_request($graph_url, array(), 'GET');
if(is_object($graph_result) && !empty($graph_result->data)) {
$data = json_decode($graph_result->data);
$going = $data->attending_count;
$invited = $data->invited_count;
return array('going' => $going, 'invited' => $invited);
}
return false;
}
return false;
}
Try
SELECT eid , attending_count, unsure_count,all_members_count FROM event WHERE eid ="event"

Categories