Algorithm optimization in PHP app - php

I'm working on a web application project which displays a list of results to the customer, with pictures, description and some other info. I want to optimize the routine responsible for displaying the results.
Let's say that we have a total of 200 results (products). For each one of them a function is called (let's call it DisplayResults), that fetches some pictures, description, and some other stuff.
DisplayResults currently is within a foreach loop, so as I already mentioned, for each one of the results we have a new function call.
I'd like to ask: how can I optimize this sequence? If I fetch all the info needed to display with a function OUTSIDE the foreach loop (for all the results at once), will I see some difference?
Thank you in advance
EDIT: I'm already using pagination. The data have been already fetched from the database and are stored in an array, so no need for SQL optimization at this point, in my opinion...
EDIT #2: This is how foreach-loop looks like:
foreach ($total['product_data'] as $product_data) {
$tags['$$searchProductList'] .= DisplayResults($product_data);
}
And this is how DisplayResults looks like:
function DisplayResults ($data) {
$tags['$$Description'] = substr($data['description'],0,70)." ...";
$tags['$$FeaturesList'] = getFeatures($data['features']);
$tags['$$PhotosList'] = getPhotos($data['photos']);
$tags['$$Offers'] = getOffers($data['offers']);
.
.
.
.
}
The $data variable contains all the information fetched from the DB for the current result.

Related

Turn a wpdb query result that reveals one row into individual variables (using shortcodes if that matters)

First post on stackoverflow. I have been following this site for a long time, and usually find what im looking for. But this has me perplexed.
Let me set the stage. I am developing a web driven program. I have Wordpress, with the Divi theme from Elegant Themes. and I am using shortcodes to insert into the modules. I am a newbie (this says it all.)
Here is my problem. I have run a wpdb query that returns a single row of results.
$editresult = $wpdb->get_results ("SELECT `serialnumber`, `batttype`, `cells`, `fullvolts` FROM listbattery WHERE serialnumber = '$serialnumber'", ARRAY_A);
When I vardump this, i get the following.
array(1) {[0]=>array(4) {["serialnumber"]=>string(10)"battery #2" ["batttype"]=>string(5) "NiCad" ["cells"]=>string(1) "8"["fullvolts"]=>string(6)"12.125"}}
So with that being said, I know that the query is working fine. I know that I am receiving the information. What I can't for the life of me figure out, is how to turn the results from each column into individual variables, so that I can insert each variable randomly throughout my page.
I have tried about 8 different methods so far. I hope you guys can help! thanks!!!
You can loop through the result:
foreach($editresult as $result) {
$serialnumber = $result['serialnumber'];
$batttype = $result['batttype'];
$cells = $result['cells'];
$fullvolts = $result['fullvolts'];
}
If only one row is expected to be returned, you can do the following
$editresult = $wpdb->get_row("SELECT `serialnumber`, `batttype`, `cells`, `fullvolts` FROM listbattery WHERE serialnumber = '$serialnumber'", ARRAY_A);
Then you can access returned values like
$editresult['serialnumber']
$editresult['batttype']
$editresult['cells']
$editresult['fullvolts']
or if you change ARRAY_A to OBJECT, you will be able to access these values like so
$editresult->serialnumber
$editresult->batttype
$editresult->cells
$editresult->fullvolts
There is no need in get_results and foreach like shown in #nanodanger's answer if you always expect to get only 1 row

Creating multiple boxes in PHP from MySQL

I have made a simple PHP news system that just basically displays information from a MySQL database that I've made, it also uses CSS for a rounded box, but, I also want it to create multiple rounded boxes displaying different news, so, to sum it up, I just want a code that will create a different box for each result.
Inside of your PHP code you will want to put your sql statement within a foreach loop to put each result into their own box.
Here is an easy example:
$dbh = db connection
$result = "SELECT new FROM news;";
$stmt = $dbh->prepare($result);
$stmt->execute();
$newEach = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($newEach as $val){
foreach($val as $key=>$news){
echo '<div class="box">' . $news . '</div>';
}
}
There is probably a better way to get the individual items without having to do a nested foreach but so far I have been unable to find a way that works this well when wanting individual results from a select query.

Is there a way to combine independent functions of a page into single and query once to distribute fetched data individually

First of all, it's an idea, need to share because its solution is not present to me. But if applicable, it can help many PHP developer as well.
I'm developing a WordPress Ad Manager Plugin. Very simple thought, get an image URL into db with an id, and fetch the URL and show them with <img> tag. In my show ad function I did something like this:
<?php
function show_ad($id){
global $wpdb;
$table = $wpdb->prefix . "my_ad";
$query = $wpdb->get_results(
"SELECT *
FROM $table
WHERE id = $id;
");
$output = echo '<img src="'. $query[0]->img_url .'"/>';
return $output;
}
?>
The ad can be shown by any of these ways: PHP Function in Template (<?php show_ad($); ?>), Shortcode, Sidebar Widget. In all the cases the image showing process will be the same function.
Suppose, I have a site, where I added 20 ads into the plugin db. Now I want to show 10 of them into 10 different places, 10 different <div>s. in the same page. So what the function is doing, using the same function in 10 different places means 10 Individual db Queries. And 10 db Queries means 10 times hit to db.
So, I'm seeking a way to combine all the function into one and execute a single db query to fetch data. I'm dreaming something like the following. Assuming there are 10 different ad places in my page:
<?php
// A TOTAL FICTIONOUS CODE BLOCK
if( function_in_this_page_exists( 'show_ad' ) ) {
$function_array = make_them_array_with_vallues();
//so function_array looks like: array( '2','4','1','5','8','10','15', ... )
//execute the combined query function
//and query the db once
$query_result_array = combined_query_function();
//so the $query_result_array looks like: array('2'=>'http://url2.com','4'=>'http://url4.com','1'=>'http://url1.com', ...)
//now, distribute the data to the individual function where they are
//by executing another function that distribute fetched data where their id belongs
distribute_array_data_to_functions($query_result_array);
}
?>
Though it's a fictionous code block, but [if possible], with this way a simple db query can do all the individual queries instead. I don't think such a function-fetching-with-parameter thing is present now in PHP. Any idea?
Firstly, you might use the MySQL keyword IN to fetch more than one id.
Secondly, just write your processing function for the returned data-set as you imagined.
In other words, build the content, insert image URL for each for the ids.
After that, you might think about caching the query and caching the generated content.
$array_with_ids = array('1','2','3');
$sql = 'SELECT *
FROM `table`
WHERE `id` IN (' . implode(',', array_map('intval', $array)) . ')';

How to store search conditions with php and Codeigniter?

I have small problem.
I've coded a full website in php using CodeIgniter framework. One of my modules is search module, it contains text input with keyword and three select lists with filtering criterias.
That's ok, when I'm searching something - result's listing pagination is done via URL like that:
mysite.com/$keyword/$criteria1/$criteria2/$criteria3/$offset
works like a charm.
But when I'm entering into one of my images (it's image gallery) I want to have an option to go into NEXT and PREVIOUS image from my search results - the ones which I entered this image from.
I'm solving this case now in this way - I have session table called 'search_conditions' and I'm storing values of keyword and my three criterias there, but that's quite not comfortable, because why if someone opens second window and search something else there?
Then all of his searches in another windows or tabs are getting the same criteria - because with every new search, user overwrite the session value.
My next and previous functions:
public function next($count)
{
$search = $this->session->userdata('search_conditions'); //getting session table and overwriting it
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count, 1);
}
public function previous($count)
{
$search = $this->session->userdata('search_conditions');
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count-2, 1);
}
Can you recommend me some other, more comfortable solution, because this seems not to be good...
: )
Thank you!
Add an index to the $search_conditions variable:
$search_conditions[1]['catid']
$search_conditions[1]['brandid']
...
then refer to it with a controller's or config variable. This way you can allow one session to store multiple search conditions.
But I would recommend you drop storing the search condition in session. Instead, just pass it with the URI. Session data, in the case you describe, work as an intermediary; you don't need it. Use the Pagination Class and pass the search page number, not the direction (next or previous) to the URI.
Do not worry that the URI may look ugly - it only depends on what user searches for, and it's still friendly to share. Your only concern is if the GET string does not extend the limited length.
Pull the segments from the URI in your next() and previous() functions. Use the codeigniter URL helper. That should allow you to pass the different search criterion as variables to the next page, this would also remove your need to use the session.

PHPFlickr script...could this be cleaner/leaner?

OK, here's my dilemma:
I've read all over about how many guys want to be able to display a set of images from Flickr using PHPFlickr, but lament on how the API for PhotoSets does not put individual photo descriptions. Some have tried to set up their PHP so it will pull the description on each photo as the script assembles the gallery on the page. However, the method has shown how slow and inefficient it can be.
I caught an idea elsewhere of creating a string of comma separated values with the photo ID and the description. I'd store it on the MySQL database and then call upon it when I have my script assemble the gallery on the page. I'd use explode to create an array of the photo ID and its description, then call on that to fill in the gaps...thus less API calls and a faster page.
So in the back-end admin, I have a form where I set up the information for the gallery, and I hand a Set ID. The script would then go through and make this string of separated values ("|~|" as a separation). Here's what I came up with:
include("phpFlickr.php");
$f = new phpFlickr("< api >");
$descArray = "";
// This will create an Array of Photo ID from the Set ID.
// $setFeed is the set ID brought in from the form.
$photos = $f->photosets_getPhotos($setFeed);
foreach ($photos['photoset']['photo'] as $photo) {
$returnDesc = array();
$photoID = $photo['id'];
$rsp = $f->photos_getInfo($photoID);
foreach ($rsp as $pic) {
$returnDesc[] = htmlspecialchars($pic['description'], ENT_QUOTES);
}
$descArray .= $photoID."|~|".$returnDesc[0]."|~|";
}
The string $descArray would then be placed in the MySQL string that puts it into the database with other information brought in from the form.
My first question is was I correct in using a second foreach loop to get those descriptions? I tried following other examples all over the net that didn't use that, but they never worked. When I brought on the second foreach, then it worked. Should I have done something else?
I noticed the data returned would be two entries. One being the description, and the other just an "o"...hence the array $returnDesc so I could just get the one string I wanted and not the other.
Second question is if I made this too complicated or not. I like to try to learn to write cleaner/leaner code, and was looking for opinions.
Suggestions on improvement are welcome. Thank you in advance.
I'm not 100% sure as I've just browsed the source for phpFlickr, and looked the the Flickr API for the getInfo() call. But let me have a go anyway :)
First off, it looks like you shouldn't need that loop, like you mention. What does the output of print_r($rsp); look like? It could be that $rsp is an array with 1 element, in which case you could ditch the inner loop and replace it with something like $pic = $rsp[0]; $desc = $pic['description'];
Also, I'd create a new "description" column in your database table (that has the photo id as the primary key), and store the description in their on its own. Parsing db fields like that is a bit of a nightmare. Lastly, you might want to force htmlspecialchars to work in UTF8 mode, cause I don't think it does by default. From memory, the third parameter is the content encoding.
edit: doesn't phpFlickr have its own caching system? Why not use that and make the cache size massive? Seems like you might be re-inventing the wheel here... maybe all you need to do is increase the cache size, and make a getDescription function:
function getDescription ($id)
{
$rsp = $phpFlickr->photos_getInfo ($id);
$pic = $rsp[0];
return $pic['description'];
}

Categories