I'm working on a project that connects to an external API. I have already made the connection and I've implemented several functions to retrieve the data, that's all working fine.
The following function however, works exactly like it should, only it slows down my website significantly ( 25 seconds + ).
Is this because of the nested foreach loop? And what can i do to refactor the code?
/**
* #param $acti
*/
function getBijeenkomstenFromAct ($acti) {
$acties = array();
foreach ($acti as $act) {
$bijeenkomsten = $this->getBijeenkomstenFromID($act['id']);
if (in_array('Doorlopende activiteit', $act['type'])) {
foreach ($bijeenkomsten as $bijeenkomst) {
$acties[] = array(
'id' => $act['id'],
'Naam' => $act['titel'],
'interval' => $act['interval'],
'activiteit' => $bijeenkomst['activiteit'],
'datum' => $bijeenkomst['datum']
);
}
} else {
$acties[] = array (
'id' => $act['id'],
'type' => $act['type'],
'activiteit' => $act['titel'],
'interval' => $act['interval'],
'dag' => $act['dag'],
'starttijd' => $act['starttijd'],
'eindtijd' => $act['eindtijd']
);
}
}
return $acties;
}
The function "getBijeenkomstenfromID" is working fine and on it's own not slow at all. Just to be sure, here is the function:
/**
* #param $activitieitID
*
* #return mixed
*
*/
public function getBijeenkomstenFromID($activitieitID) {
$options = array(
//'datumVan' => date('Y-m-d'),
'activiteit' => array (
'activiteit' => $activitieitID
),
'limit' => 5,
'datumVan' => date(("Y-m-d"))
);
$bijeenkomsten = $this->webservice->activiteitBijeenkomstOverzicht($this->api_key, $options);
return $bijeenkomsten;
}
It looks like you're calling on the API from within the first foreach loop, which is not efficient.
Every time you do this:
$bijeenkomsten = $this->getBijeenkomstenFromID($act['id']);
you're adding a lot of "dead" time to your script since you have to put on with network latency, the time you need to allow for the API to actually do the work and transmit it back to you. Even though this may be quick (let's say 100ms total), if your first foreach loop iterates 100 times, you already have accumulated 10 seconds of waiting, and that's before getBijeenkomstenFromAct ($acti) has done any real processing.
The best practice here would be to split this if possible. My suggestion:
Make getBijeenkomstenFromID($activitieitID) run asynchronously on its own for all the IDs you need to lookup in the API. The key here is for it to run as a separate process and then have it pass the array it constructs to getBijeenkomstenFromAct so that it can loop and process it happily.
So yes, basically I'm suggestion that you orchestrate your process backwards for efficiency's sake
Look into curl_multi: http://php.net/manual/en/function.curl-multi-exec.php
It will let you call an external API asynchronously and process the returns all at once. Be aware that APIs often have their own limitations on asynchronous calls, and common sense dictates that you probably shouldn't be hammering a website with 200 separate calls. But if your number of calls is under a dozen or two (and the API allows it), curl_multi will do nicely.
Related
I'm an intermediate programmer who works with PHP mostly. Recently, I noticed that many PHP developers use arrays as function arguments in their code. I'm little sceptic of using arrays like that, as some of the people in my workplace said that it's not the best practice.
For example, I have this piece of code in one of my WordPress projects right now, it might not make sense to you completely, but it's relevant:
<?php
/**
* Print a list of featured posts.
*
* #param $args Array Function Arguments
* #return $html String The final markup
*/
if( function_exists( 'abc_featured_posts_list' ) ) :
function abc_featured_posts_list( $args = array(
'number' => 8,
'image' => 'path/to/default.image',
'wrapper' => false,
'style' => 'minimal'
) ) {
// Storage for the list markup
$html = null;
...
...
return html;
}
endif;
?>
It's the first time I'm passing arguments like this in a PHP function. Is it the right way to do that? What is the advantage of using an array over a bunch of variables in such a case?
I'm writing a PHP web app that uses XML documents from an API. I have to construct many products from the returned XML data.
What I'm doing right now is using xpath and a loop to pull all of the objects into an array of sub-arrays. Then I loop through the array of arrays and pull specific arrays into their own named array. Is there a way to do this with a function or class constructor?
My current code looks something like this:
if ( $products_results_list[$key]["sChgDesc"] == "Small Box" ) {
$small_box = array(
"ChargeDescID" => $products_results_list[$key]["ChargeDescID"],
"sChgDesc" => $products_results_list[$key]["sChgDesc"],
"dcPrice" => $products_results_list[$key]["dcPrice"],
"dcTax1Rate" => ".0" . $products_results_list[$key]["dcTax1Rate"],
"dcInStock" => $products_results_list[$key]["dcInStock"],
);
}
After writing the above if statement about 8 times, with many more times needed, I'm thinking there must be a better practice than just writing everything out.
I want to do something like:
product_constructor($argument, $product_name) {
if ( $arguement ) {
$product_name = array(
"ChargeDescID" => $products_results_list[$key]["ChargeDescID"],
"sChgDesc" => $products_results_list[$key]["sChgDesc"],
"dcPrice" => $products_results_list[$key]["dcPrice"],
"dcTax1Rate" => ".0" . $products_results_list[$key]["dcTax1Rate"],
"dcInStock" => $products_results_list[$key]["dcInStock"],
);
}
and then just call the function or constructor as needed like:
product_constructor( '$products_results_list[$key]["sChgDesc"] == "Small Box"', '$small_box');
I actually tried the above code, but it was throwing errors. Despite working with PHP daily, I still don't know much about constructors, and figured this might be the perfect opportunity to learn how to do this correctly.
I'm not sure if classes are the right choice for this since I'm going to need to pull the products themselves into product package classes later.
I need to clear data from the class created in parse.com'm using CURL with PHP.
However, I have to put in a foreach so that data and it makes very heavy processing.
Is there any way to delete all rows automated class?
foreach($request->results as $item){
$params = array(
'className' => 'UltimaMilha',
'objectId' => 'QE0oL2R4X6,xc3rzlKF7U'
);
$request = $parse->delete($params);
}
Hi guys I have the method below for counting within polygons in a mongodb:
public function countWithinPolygon($polygon, $tags = array())
{
// var_dump($polygon);
// var_dump($polygon->getPoints());exit();
$query = array(
'point' => array(
'$within' => array(
'$polygon' => $polygon->getPoints()->first()->toArray(true)
)
)
);
if($tags)
{
$query['tags'] = array(
'$all' => $tags
);
}
return parent::count($query);
}
For some queries with small amounts of data it is just okay. On larger datasets containing 4000+ calls the execution time is truely pathetic and can take hours. On average it takes three hours to execute. Any ideas or hints on a better way to write this to save time and optimize this query?
The issue was fixed by ensuring an index like so : db.polygon.ensureIndex({'GeoJSON.geometry':'2dsphere'});
I am working with an array of tokens for an HTML template. Two of them ('{SYS_MENU}' and '{SUB_MENU}') are used to generate control buttons for the web application. Right now the buttons show up on the login page before the user's credential's are validated, and I need to change the code so that the buttons are hidden until after users login and reach the main menu. When someone types the http: address into their browser and arrives at the login page the system starts a session for them in the MySQL sessions table with USER_ID = 0. After they login the USER_ID changes to whatever number was assigned to them at initial registration (Example: USER_ID = 54), and after they logout at the end of the session back to 0. Tying this constant to the buttons seems like the best solution and I have found it to work in the past under similar circumstances.
Here is the original array:
$template_vars = array(
'{LANG_DIR}' => $lang_text_dir,
'{TITLE}' => theme_page_title($section),
'{CHARSET}' => $charset,
'{META}' => $meta,
'{GAL_NAME}' => $CONFIG['gallery_name'],
'{GAL_DESCRIPTION}' => $CONFIG['gallery_description'],
'{SYS_MENU}' => theme_main_menu('sys_menu'),
'{SUB_MENU}' => theme_main_menu('sub_menu'),
'{ADMIN_MENU}' => theme_admin_mode_menu(),
'{CUSTOM_HEADER}' => $custom_header,
'{JAVASCRIPT}' => theme_javascript_head(),
'{MESSAGE_BLOCK}' => theme_display_message_block(),
);
The first thing I did was to work with the references directly in the HTML template. I saw an example on w3schools that made it look like you could just type a PHP script into HTML and have it resolve. That didn't do anything except echo a bunch of text randomly into the page. I then found another citation that said you had to activate the PHP with an .HTACCESS entry before it would work directly in HTML. But that didn't close the deal either.
I know that changing '{SYS_MENU}' and '{SUB_MENU}' values in the array to => "", produces the results that I want (I.E. make the menu buttons disappear). So my next thought was I'll create an IF statement that returns two versions of the array based on circumstances, something like:
if(USER_ID != 0)
{
return $template_vars = //FIRST VERSION OF ARRAY WITH FULL VALUES//
}
else
{
return $template_vars = //SECOND VERSION OF ARRAY WITH ONLY => ""//
}
But all that did was cause the application load to terminate at a white screen with no error feedback.
My most recent attempt came from something I read here on Stack Overflow. I know that you cannot put IF statements into an array. But the article at this link described a workaround:
If statement within an array declaration ...is that possible?
So I rewrote the array as follows:
template_vars = array(
'{LANG_DIR}' => $lang_text_dir,
'{TITLE}' => theme_page_title($section),
'{CHARSET}' => $charset,
'{META}' => $meta,
'{GAL_NAME}' => $CONFIG['gallery_name'],
'{GAL_DESCRIPTION}' => $CONFIG['gallery_description'],
'{SYS_MENU}' => ('USER_ID != 0' ? theme_main_menu('sys_menu') : ""),
'{SUB_MENU}' => ('USER_ID != 0' ? theme_main_menu('sub_menu') : ""),
'{ADMIN_MENU}' => theme_admin_mode_menu(),
'{CUSTOM_HEADER}' => $custom_header,
'{JAVASCRIPT}' => theme_javascript_head(),
'{MESSAGE_BLOCK}' => theme_display_message_block(),
);
But that seems to have no effect at all. The application doesn't crash but the buttons are static whether you are logged in or logged out.
My question is: What am I missing? I can see that this is possible. But I've been trying things for a day and a half and just seem to be dancing around the solution. Your thoughts would be greatly appreciated.
The problem here is that you are calling return. With a global include file like this there is not context to return to so the application terminates. What you want to do is just assign the variables.
if(USER_ID != 0)
{
$template_vars = //FIRST VERSION OF ARRAY WITH FULL VALUES//
}
else
{
$template_vars = //SECOND VERSION OF ARRAY WITH ONLY => ""//
}