Im making a big APi call, i have over 6000 records. Out of those 6000 i get 200 per page. So if we divide 6000 by 200 we get 30 pages in total.
So if I would want to get all records I'd need to make 30 different requests. I can speficy the amount per page in my request url parameters. Right now it looks like this:
$getRequest = $CallMonkeyApi->makeApiCall('GET','/address/get-all?apiKey=secret&page=1&size=200');
In the url you see a parameter "page=1" I would like this number to be dynamic from a loop that stops at 30. But I dont know where to start.
You can do this with a "for" loop
//An array for results
$getRequests = array();
//For every occurance where `x` is less than or equal to 30
for( $x = 1; $x<=30; $x++ ){
//Build the path to API call
$path = "/address/get-all?apiKey=secret&page=" . $x . "&size=200";
//Make API call and store the output on the $getRequests array of results
$getRequests[] = $CallMonkeyApi->makeApiCall('GET', $path);
}
Then you can access your $getRequests array by using $getRequests[$pageNumber]. So, for example, if I wanted to see page 5, i'd do print_r( $getRequests[4] ).
Note that the page number will be one less in the array because arrays start at 0.
Related
I have a function that calls an API but want to create batches and call these every x second.
My form contains a textarea (Titles) where a list is added and are formatted SKU|Title on each line.
Within my code take each line and split where pipe is, i use the SKU part to know where the search terms belongs to and the Title part is used on the API search.
What i need to do now is split the 1000 (or however amount) inputted search lines into smaller batches, like 10 searches every 5 seconds and work through the titles.
Current Setup
<?php
function search_items($title, $filetype, $resultamount) {
foreach(explode("\r\n", $title) as $line) {
$strip = explode("|",$line);
// This is where the API Runs
// I use $strip[1] to get the Title to search in the API request
}
}
?>
I think the below could work but kept getting errors like array to string error
$batches_of = 10;
$search_array = explode("\r\n", $title);
$batch = array_chunk($search_array, $batches_of);
foreach($batch as $b) {
foreach ($b as $key => $value) {
print $key;
}
sleep (5);
}
Update
Ok so i have been trying this for a while and seem to have got something working and looks to do as intended, no errors and take a while but its as expected (note this is not a production model), any feedback on the below?
// Title = Multiple Lines from Textarea, Example Title 32306|Samsung Galaxy S20 256GB Black
// Filetype = I have a custom If / Else statement, if form has one selection display it differently (File Type 1 or 2)
// ResultAmount = How many results do i want to retrieve for each searched title, Example 1 - 10
function search_items($title, $filetype, $resultamount) {
// Set the amount of Batches to create from the Total Submitted amount in form
$batch_of = 10;
// Create array for each line item
$my_array = explode("\r\n", $title);
// Create array Batches
$batch = array_chunk($my_array, $batch_of);
foreach($batch as $line) {
foreach ($line as $key => $value) {
// Seperate the line items to Get SKU ($strip[0]) and get Title ($strip[1])
$strip = explode("|",$value);
// API request variables using CURL
$endpoint = 'http://web.com/services/search';
// The Query, now i will use the Product Name and appende $query to my search URL
$query = ''.str_replace(str_split('\\/:*?"<>|()[]-'), '%20', $strip[1]).'';
// My API Data and responses will be below
}
// Wait 2 Seconds before the next batch
sleep (2);
}
}
I have just discovered you can get pagination results through the api by passing in the page parameter like so:
$projects = $client->get('projects/147/time-records?page=3')->getJson();
Is there a way of knowing how many time records a project has so I know how many times I need to paginate?
Alternatively, how would I go about retrieving several pages worth of data - i'm struggling with the code!
I have created an issue on Github - will await a response.
For now, I do the following:
// Get all the projects
// Set the page number
$page = 1;
// Create an empty array
$project_records = array();
// Get the first page of results
$project_records_results = $client->get('projects?page=' . $page)->getJson();
// Merge the results with base array
$project_records = array_merge($project_records, $project_records_results);
// Get the next page of results,
// if it returns something merge with the base array and continue
while ($project_records_results = $client->get('projects?page=' . ++$page)->getJson()) {
$project_records = array_merge($project_records, $project_records_results);
}
Sure. All paginated results will include following headers:
X-Angie-PaginationCurrentPage - indicates current page
X-Angie-PaginationItemsPerPage - indicates number of items per page
X-Angie-PaginationTotalItems - indicates number of items in the entire data set.
When you get header values, simple:
$total_pages = ceil($total_items_header_value / $items_per_page_header_value);
will give you number of pages that are in the collection.
Alternative: You can iterate through pages (by starting with page GET parameter set to 1, and incrementing it) until you get an empty result (page with no records). Page that returns no records is the last page.
Please note, that the headers are now all lowercase (v1)!
So the answer above should be corrected.
To get them call:
$headers = $client->get($path)->getHeaders();
Working code example from /api/v1/:
$paginationCurrentPage = isset($headers['x-angie-paginationcurrentpage'][0]) ? $headers['x-angie-paginationcurrentpage'][0] : NULL;
$paginationItemsPerPage = isset($headers['x-angie-paginationitemsperpage'][0]) ? $headers['x-angie-paginationitemsperpage'][0] : NULL;
$paginationTotalItems = isset($headers['x-angie-paginationtotalitems'][0]) ? $headers['x-angie-paginationtotalitems'][0] : NULL;
I am creating a PHP class that use a 3rd party API. The API has a method with this request URL structure:
https://api.domain.com/path/sales?page=x
Where "x" is the page number.
Each page return 50 sales and I need to return an undefined number of pages for each user (depending on the user sales) and store some data from each sale.
I have already created some methods that get the data from the URL, decode and create a new array with the desired data, but only with the first page request.
Now I want to create a method that check if is there another page, and if there is, get it and make the check again
How can I check if there is another page? And how to create a loop that get another page if there is one?
I have already this code, but it create an infinite loop.
require('classes/class.example_api.php');
$my_class = new Example_API;
$page = 1;
$sales_url = $my_class->sales_url( $page );
$url = $my_class->get_data($sales_url);
while ( !empty($url) ) {
$page++;
$sales_url = $my_class->sales_url( $page );
$url = $my_class->get_data($sales_url);
}
I don't use CURL, I use file_get_content. When I request a page out of range, I get this result:
string(2) "[]"
And this other after json_decode:
array(0) { }
From your input, in the while loop, you change the $url (which actually holds the data return by the API call) and this is checked for emptiness, if I'm correct.
$url = $my_class->get_data($sales_url);
If the above is just the original response (so in case of page out of range a string "[]"), it will never get empty("[]") to true. So my guess is that the return value from get_data is this string, while it should be the actual array/json even if the result is empty (ie I suspect that you perform the json_decode once you have collected the data e.g. outside the loop).
If this is the case, my suggestion would be to either check for "[]" in the loop (e.g. while ($url !== "[]")) or within the loop decode the response data ($url = json_decode($url)).
From my experience with several API's, the response returns the number of rows found, and x number per page starting with page 1.
In your case, if the response has the number of rows then just divide it by the x number page and loop through the results as page numbers.
$results = 1000;
$perPage = 50;
$pages = ceil($results/$perPage);
for (i=1; $i <= $pages; $i++){
// execute your api call and store the results
}
Hope this help.
From the responses you've shown, you get an empty array if there are no results. In that case, you could use the empty method in a loop to determine if there's anything to report:
// Craft the initial request URL
$page = 1;
$url = 'https://api.domain.com/path/sales?page=' . $page;
// Now start looping
while (!empty(file_get_contents($url)) {
// There's data here, do something with it
// And set the new URL for the next page
$url = 'https://api.domain.com/path/sales?page=' . ++$page;
}
That way it will keep looping over all the pages, until there is no more data.
Check http response headers for total number of items in set
I'm building a website that relies on reading through the XML produced by Tumblr for my photoblog and extracting blog post URLs and image URLs for display and linking.
I've written code in PHP that parses the XML and constructs an outer and inner loops to deal with how Tumblr limits the max number of posts to 50 on any request. The loops should process requests that return batches of 50 URLs and in the final loop only deal with the remainder.
Currently the blog has 53 posts so the code has logic that determines that 2 requests should be read in 2 loops:
The first loop reads: http://abstractmueller.tumblr.com/api/read?start=0&num=50
The second loops reads: http://abstractmueller.tumblr.com/api/read?start=50&num=3
In both cases the XML is loaded into the $xml variable and then parsed for specific data that is collected in an inner loop. When executed, it should just produce a list of image numbers, blog post URLs and image URLs through the entire set of loops.
When I execute this code, the loop always breaks after parsing 20 items as long as I read from XML file returned from the request. If I test the code removing references to the XML output and just letting the code run through counting loops with simple output it works.
I don't understand what in the XML file might be causing this -- through there is a subtle change in the some of the XML data after the first 20 posts.
Can anyone help?
Here is the code:
<?php
// Get xml file from Tumblr API and load
$request_url = "http://abstractmueller.tumblr.com/api/read";
$xml = simplexml_load_file($request_url);
// Get total number of posts, set max number of posts and calculate loop critical info
$posts_data = $xml->posts[0]->attributes();
$posts_max = 50;
$loop_number = ceil($posts_data['total']/$posts_max);
$loop_remainder = $posts_data['total']%$posts_max;
echo '<p>Total posts = '.$posts_data['total'].'</p>';
echo '<p>Loop number = '.$loop_number.'</p>';
?>
<div>
<?php
// Start outer loops to fetch up to 50 post-related image urls each fetch
for ($outer_loop = 1; $outer_loop <= $loop_number; $outer_loop++){
$post_start = ($outer_loop - 1) * $posts_max;
echo '<p>Current loop = '.$outer_loop.'</p>';
// Branch looping so first branch loops through each batch of 50 images, then use last loop to limit looping to the remainder
if ($outer_loop < $loop_number) {
echo '<p>Post start = '.$post_start.'</p>';
echo '<p>Loop end = '.($post_start + $posts_max-1).'</p>';
$request_url = 'http://abstractmueller.tumblr.com/api/read?start='.$post_start.'&num='.$posts_max;
echo '<p>XML URL '.$request_url.'</p>';
// Get post URLs and image URLs in batches of 50
for ($img_num = ($post_start); $img_num < ($post_start + $posts_max); $img_num++) {
$blog_url = $xml->posts->post[$img_num]->attributes();
$photo_url = $xml->posts->post[$img_num]->{'photo-url'}[2];
echo '<p>Image '.$img_num.' Blog URL '.$blog_url['url'].' Image URL '.$photo_url.'</p>';
}
} else {
echo '<p>Post start = '.$post_start.'</p>';
echo '<p>Loop end = '.($post_start + $loop_remainder - 1).'</p>';
$request_url = 'http://abstractmueller.tumblr.com/api/read?start='.$post_start.'&num='.$loop_remainder;
echo '<p>XML URL '.$request_url.'</p>';
// Get post URLs and image URLs up to the total remainder
for ($img_num = $post_start; $img_num <= $loop_remainder + $posts_max; $img_num++) {
$blog_url = $xml->posts->post[$img_num]->attributes();
$photo_url = $xml->posts->post[$img_num]->{'photo-url'}[2];
echo '<p>Image '.$img_num.' Blog URL '.$blog_url['url'].' Image URL '.$photo_url.'</p>';
}
}
}
?>
<div>
there. I'm having a problem with creating arrays in certain conditions in php, i'll try to explain. Here's my code:
for ($i = 1; $i < $tamanho_array_afundamento; $i++) {
if ($array_afundamento[$i] - $array_afundamento[$i - 1] > 1) {
$a = $array_afundamento[$i - 1];
$con->query('CREATE TABLE IF NOT EXISTS afunda_$a
SELECT (L1_forma_tensao_max + L1_forma_tensao_min)/2 as L1_forma_tensao, (L2_forma_tensao_max + L2_forma_tensao_min)/2 as L2_forma_tensao, (L3_forma_tensao_max + L3_forma_tensao_min)/2 as L3_forma_tensao
FROM afundamento
WHERE id > $prevNum AND id < $a');
$tabelas_intervalos_afunda1 = ($con->query("SELECT * FROM afunda_$a");
while ($row = $tabelas_intervalos_afunda->fetch(PDO::FETCH_ASSOC)) {
$array_forma_onda_fase1_afund[] = $row['L1_forma_tensao'];
$array_forma_onda_fase2_afund[] = $row['L2_forma_tensao'];
$array_forma_onda_fase3_afund[] = $row['L3_forma_tensao'];
}
$prevNum = $a;
}
}
So as u can see, i have an if statement in a for loop, what i'm wishing to do is to create
one set of:
{
$array_forma_onda_fase1_afund[] = $row['L1_forma_tensao'];
$array_forma_onda_fase2_afund[] = $row['L2_forma_tensao'];
$array_forma_onda_fase3_afund[] = $row['L3_forma_tensao'];
}
every time the if statement is runned. I was trying replacing this in the original code:
{
$array_forma_onda_fase1_afund_$a[] = $row['L1_forma_tensao'];
$array_forma_onda_fase2_afund_$a[] = $row['L2_forma_tensao'];
$array_forma_onda_fase3_afund_$a[] = $row['L3_forma_tensao'];
}
so as $a is changed everytime the if statement is accessed, i could have a different set of these arrays for everytime the if statement is accessed, but php doesn't accept this and i wouldn't have a very good result, though if i can reach it i would be pleased.
But my goal is to get:
{
$array_forma_onda_fase1_afund_1[] = $row['L1_forma_tensao'];
$array_forma_onda_fase2_afund_1[] = $row['L2_forma_tensao'];
$array_forma_onda_fase3_afund_1[] = $row['L3_forma_tensao'];
}
{
$array_forma_onda_fase1_afund_2[] = $row['L1_forma_tensao'];
$array_forma_onda_fase2_afund_2[] = $row['L2_forma_tensao'];
$array_forma_onda_fase3_afund_2[] = $row['L3_forma_tensao'];
}
...
where the last number represents the array retrieved for the n-th time the if statement runned. Does someone have a tip for it?
Thanks in advance! Would appreciate any help.
EDIT
As asked, my real world terms is as follows:
I have a table from which i need to take all the data that is inside a given interval. BUT, there's a problem, my data is a sine function whose amplitude may change indefinite times (the data bank is entered by the user) and, when the amplitude goes inside that interval, i need to make some operations like getting the least value achieved while the data was inside that interval and some other parameters, for each interval separately, (That's why i created all those tables.) and count how many times it happpened.
So, in order to make one of the operations, i need an array with the data for each time the databank entered by the user goes in that interval (given by the limits of the create query.).
If i were not clear, just tell me please!
EDIT 2
Here's the image of part of the table i'm working with:
http://postimg.org/image/5vegnk043/
so, when the sine gets inside the interval i need, it can be seen by the L1_RMS column, who accuses it, so it's when i need to get the interval data until it gets outside the interval. But it may happens as many times as this table entered by the user brings it on and we need to bear in mind that i need all the intervals separately to deal with the data of each one.
Physics uh?
You can do what you wanted with the arrays, it's not pretty, but it's possible.
You can dynamically name your arrays with the _$a in the end, Variables variables, such as:
${"array_forma_onda_fase3_afund_" . $a}[] = "fisica é medo";