Why doesn't my loop echo for all iterations? - php

I'm trying to make a tag cloud system getting its values from PHP/SQL but it seems to work erratically, only giving a handful of the expected results. What's causing this odd behaviour?
As far as I can tell it should loop through a total of 20 times (0-19) and each time it adds a string into an array.
The system starts out by getting the 20 most popular tags from my database in descending order, once its got this I create a string and set the font size. This string is then stored in an array and is echoed out using a random number array giving a random order to the cloud.
I then increase the value of i for my loop iteration whilst decreasing the font size for the next less popular tag.
<h1>Tag Cloud</h1>
<?php
$sql = "SELECT * FROM tags ORDER BY count DESC";
$tags_query = mysqli_query($db_conx, $sql);
$i = 0;
$tag_array = array();
$tag_size_max = 36;
$tag_size_min = 16;
$numbers = range(0, 19);
shuffle($numbers);
do {
$row = mysqli_fetch_array($tags_query, MYSQLI_ASSOC);
$tag = $row["tag"];
$tag_count = $row["count"];
$tag_array[] = "<p style='font-size:".$tag_size_max."px; padding:0px;'>".$tag."</p>";
echo $tag_array[$numbers[$i]];
$i++;
$tag_size_max--;
} while ($i < 20);
?>
You can see it kind of working in the footer of my site http://www.vwrx-project.co.uk

It seems that you're trying to echo $tag_array element with index which isn't yet in the array itself.
You would probably need two loops - first to fill the $tag_array, and another one to echo them.
Do you have proper ERROR_LEVEL - there should be some notices about missing indexes - at least if I'm ready your code correctly ;)
Something like this:
// fill the array
for ($i=0; $i<20; $i++) {
$row = mysqli_fetch_array($tags_query, MYSQLI_ASSOC);
$tag = $row["tag"];
$tag_count = $row["count"]; // this seems to be unused
$tag_array[] = "<p style='font-size:".$tag_size_max."px; padding:0px;'>".$tag."</p>";
}
// echo the array
for ($i=0; $i<count($tag_array); $i++) {
echo $tag_array[$numbers[$i]];
}

I think the problem occurs in the following line
echo $tag_array[$numbers[$i]];
when you push to the array
$tag_array[] = "<p style='font-size:".$tag_size_max."px; padding:0px;'>".$tag."</p>";
you get an index for each tag , for example
[0] =>"<p style='font-size:".$tag_size_max."px; padding:0px;'>".$tag."</p>";
[1] =>"<p style='font-size:".$tag_size_max."px; padding:0px;'>".$tag."</p>";
for every iteration
and then in the following line you echo a random element (probably different form the one you just created )from the array by using the $number array which is not ordered after shuffling it.
I suggest you shuffle the results from the database first with
$results = array();
while($row =mysqli_fetch_array($tags_query, MYSQLI_ASSOC))
{
array_push($results, $row);
}
shuffle($results);
and then create a "normal" loop for printing in the tags using the results array.
Also if you need only 20 tags why not adding LIMIT 20 to your query to simplify the code?
Hope it helps

Related

str_replace within a while loop - PHP

I'm having a problem with str_replace within a while loop.
I've created a couple of variables before a while loop:
$c = 0; // This represents the first object within an array EG: array[0]
$i = 1; // This represents the first [image#] tag within $articleContent
What I'm trying to achieve is, when the user inputs '[image1], [image2], [image3]' etc into the $articleContent, to replace the [image#] tags with an <img src=""/> containing the file path located within the unserialized array.
The $images[$c] variable is pointing to the file path with the id of [0] within the array.
The issue:
My expectations were that the loop would naturally count through each $c and $i, labeling each [image#] and array object accordingly, then replacing the [image#] tag with the <img src='images/$imageSplit[$i]'/>, however this has not been the case.
The current functionality:
Say I have three articles being echo'd by the loop. each with three [image#] tags in [image1], [image2] and [image3]. The first article will ONLY show the first image, the second article will only show the second image, and the third article will only show the third.
If anyone could point me in the right direction for the script to replace the image tags accordingly then that'd be much appreciated.
Here is my code so far:
$sql = "SELECT * FROM articles";
$res = mysql_query($sql);
$i = 1; // [image#]
$c = 0; // Array object #
echo "<br/><br/>";
while($row = mysql_fetch_assoc($res)){
$title = $row['title']; // Grabs the title
$articles = $row['articleContent']; // Grabs the article
$images = unserialize(base64_decode($row['image']));
$imageSplit[$i] = $images[$c]; // [image1] = array[0]
$articles = str_replace("[image$i]","<img src='images/$imageSplit[$i]' width='300px' height='auto'/>","$articles");
// str_replace is only applied once per loop
echo "Title: $title<br/>
Content: $articles<br/>
c = $c<br/>
i = $i<hr/>";
// All variables, including $c and $i are both echoing out correctly, however $i is only being applied correctly once every loop
$c++;
$i++;
}
Say I have three articles being echo'd by the loop. each with three
[image#] tags in [image1], [image2] and [image3]
That means you will have to nest 2 loops: a)foreach article, b)foreach one of its images.
Here is a possible way of doing it (I commented out some of the lines that won't be needed):
$sql = "SELECT * FROM articles";
$res = mysql_query($sql);
//$i = 1; // [image#]
//$c = 0; // Array object #
echo "<br/><br/>";
while($row = mysql_fetch_assoc($res)){
$title = $row['title']; // Grabs the title
$articles = $row['articleContent']; // Grabs the article
$images = unserialize(base64_decode($row['image']));
// $imageSplit[$i] = $images[$c]; // [image1] = array[0]
foreach ($images as $index => $img_url) {
$i = $index + 1;
$articles = str_replace("[image$i]","<img src='images/$img_url' width='300px' height='auto'/>","$articles");
}
echo "Title: $title<br/>
Content: $articles<br/>
<br/>
<hr/>";
// All variables, including $c and $i are both echoing out correctly, however $i is only being applied correctly once every loop
//$c++;
//$i++;
}

PHP run query off each array variable and return results in table

I am trying to run a query off multiple array variables and display the results in a table.
The user selects 1 or more records, which includes BOL and CONTAINER. These selections are put in their own arrays and they are always an equal amount.
<?php
$bolArray = explode(',', $_POST['BOL']);
$containerArray = explode(',', $_POST['CONTAINER']);
$count = count($bolArray); // to get the total amount in the arrays
I use a FOR loop to separate each value from the 2 arrays:
for($i = 0; $i < $count; $i++)
{
$bol = $bolArray[$i];
$container = $containerArray[$i];
}
Here is the part where I'm stuck and probably where I am messing up.
I need to take each variable from the FOR loop and run query using both variables.
First, I'll start the table:
echo "<table><thead><tr><th>BOL</th><th>Container</th></thead><tbody>";
Here is where I tried a FOREACH loop:
foreach($containerArray as $container) // I am not sure if I am using this FOREACH correctly
{
And now, the query. Please take note of the variables from the first FOR loop:
$preQuery = "SELECT * FROM mainTable WHERE CONTAINER = '".$container."' AND BOL = '".$bol."'";
$preRes = mysql_query($preQuery) or die(mysql_error());
$preNum = mysql_num_rows($preRes);
I use a WHILE loop with a mysql_fetch_assoc:
while($preRow = mysql_fetch_assoc($preRes))
{
echo '<tr>'
echo '<td>'.$preRow[BOL_NUMBER].'</td>';
echo '<td>'.$preRow[CONTAINER_NUMBER].'</td>';
echo '<td>'.$preRow[ANOTHER_COLUMN].'</td>';
echo '</tr>'
}
}
echo '</tbody></table>';
?>
The query actually works. Problem is, it only returns 1 record, and it's always the last record. The user could select 4 records, but only the last record is returned in the table.
I tried to use the same query and paste it inside the first FOR loop. I echoed out the query and it displayed the same amount of times as the number of array values, but will only return data for the last record.
I do not understand what I am doing wrong. I just want to display data for each value from the array.
Edit
Here is what the code looks like when I throw the query in the first FOR loop:
echo "<table class='table table-bordered'><thead><tr><th>BOL</th><th>Container</th></tr></thead><tbody>";
for($i = 0; $i < $count; $i++)
{
$bol = $bolArray[$i];
$container = $containerArray[$i];
$preQuery = "SELECT BOL_NUMBER, CONTAINER_NUMBER FROM `intermodal_main_view` WHERE BOL_NUMBER = '". $bol ."' AND CONTAINER_NUMBER = '".$container."'";
$preRes = mysql_query($preQuery) or die();
$preNum = mysql_num_rows($preRes);
while($preRow = mysql_fetch_assoc($preRes))
{
echo '<tr>';
echo '<td>'.$preRow[BOL_NUMBER].'</td>';
echo '<td>'.$preRow[CONTAINER_NUMBER].'</td>';
echo '</tr>';
}
}
echo "</tbody></table>";
I think you can use "IN" if your POST vars are comma separated.
$preQuery = "
SELECT * FROM mainTable
WHERE CONTAINER IN ($_POST['CONTAINER'])
AND BOL IN ($_POST['BOL'])
";
$preRes = mysql_query($preQuery) or die(mysql_error());
$preNum = mysql_num_rows($preRes);
Then go to your while loop....
This would omit the need for creating an array and looping it.
Also, you need to switch to PDO for your query, and switch to parameter binding. It will take all of an hour to learn.

Separating mysql fetch array results

i have a mysql table the contains an index id, a data entry and 10 other columns called peso1, peso2, peso3...peso10. im trying to get the last 7 peso1 values for a specific id.
like:
$sql = mysql_query("SELECT * FROM table WHERE id='$id_a' ORDER BY data DESC LIMIT 0, 7");
when i try to fetch those values with mysql_fetch_array, i get all values together.
example:
while($line = mysql_fetch_array($sql)) {
echo $line['peso1'];
}
i get all peso1 values from all 7 days together. How can i get it separated?
They will appear all together because you are not separating them as you loop through them.
for example, insert a line break and you will see them on separate lines
while($line = mysql_fetch_array($sql)) {
echo $line['peso1'] ."<br />";
}
You could key it as an array like so
$myArray = array();
$i = 1;
while($line = mysql_fetch_array($sql)) {
$myArray['day'.$i] = $line['peso1'];
$i++;
}
Example use
$myArray['day1'] // returns day one value
$myArray['day2'] // returns day two value
It's not clear what you mean by "separated" so I'm going to assume you want the values as an array. Simply push each row field that you want within your while loop onto an array like this:
$arr = array();
while($line = mysql_fetch_array($sql)) {
$arr[]=$line['peso1'];
}
print_r($arr);//will show your peso1 values as individual array elements

How to split SQL query results into chunks in PHP

I am trying to break query results into chunks using PHP but can't seem to figure out how to formulate either a query or a loop to break the results into batches of four and surround those four rows with specific HTML elements.
The content is specifically a photography portfolio, where I am just attempting to display photos row by row, but the way I need to style it calls for each row to basically be a separate set of information.
This is the code I'm working with thus far:
<ul class="no-bullet">
<?php
require("connect.php");
$query = "SELECT * FROM dv_photo_work LIMIT 4";
$result = mysql_query($query, $link);
while ($row = mysql_fetch_array($result)) {
print('
<li><img alt="'.$row["img_title"].'" src="'.$row["img_slug"].'></li>');
}
?>
</ul>
I only want four images to be in that list though. And then another four in another list. Can you help me reformulate the loop to make it return four records and then begin a new query of the following four records in another list? There will be approximately 100 records in the database that I will be retrieving this from, so it would have to be able to continue until the entire table is listed.
I imagine this is similar to a pagination process, yet that is another technique that I am unfamiliar with. I'm assuming it's a simple adjustment to the query and mark-up, however I could understand it being something that requires a bit more code creativity than a simple fix.
Many thanks,
Joshie
Try this
<ul class="no-bullet">
<?php
require("connect.php");
$query = "SELECT * FROM dv_photo_work";
$result = mysql_query($query, $link);
$i =1;
while($row = mysql_fetch_array($result)) {
print('<li><img alt="'.$row["img_title"].'" src="'.$row["img_slug"].'></li>');
if ($i%4 == 0) echo "</ul><ul class='no-bullet'>";
$i++;
}
?>
</ul>
First! move that logic far away from the html, that will allow you to see the problem more clearly. Second! what about two classes a Class A that represents an n-length list of query results. Class A should be an iterator, so that a Class B can pull arbitrary length chunks of results and return appropriately sized result objects. maybe there's a third class whose instances represent the sized constrained result. So all in all three classes A representing a full list of results, B acting on a and returning instances of C which would represent your sized constrained result chunks.
This was originally a comment, but it was too long, so I had to make it an answer (sorry if it's too 'teach a man to fish' I just don't want to write php...)
Get all your results, read them into a multidimensional array, and then split them into groups with array_chunk().
$query = mysql_query("SELECT * FROM dv_photo_work",$link);
$results = array();
while($line = mysql_fetch_array($query, MYSQL_ASSOC)){
$results[] = $line;
}
$lists = array_chunk($results,4);
foreach ($lists as $list) {
echo '<ul>';
foreach ($list as $result) {
echo '<li><img alt="'.$result["img_title"].'" src="'.$result["img_slug"].'></li>'
}
echo '</ul>';
}
Here is an outline of the logic involved, using the modulus operator (%) to change the HTML at every fourth record:
$i = 0;
// within your current while-loop:
if ($i % 4 == 0) {
// $i is a multiple of 4 (including 0, the first record)
if ($i > 0) {
// finish the previous ul-tag
}
// start a new block of HTML (the ul)
}
// output the li
$i += 1;
// after the loop, close the last ul

how to grab a "random" set of items from a loop in php

Im looping through some XML nodes, and say i have between 1 and 200 of these nodes.
How can i "randomly" select a maximum of 10 of these nodes. It has to be as most ten, but as few as 1.
This is what im working with now...
$i = 0;
foreach ($butters->users->user as $user) {
if($i==10) break;
$id = $user->id;
$name = $user->screen_name;
$profimg = $user->profile_image_url;
echo "things";
$i++;
}
The difficulty is that i don't know how many i will have, but would like the pool from which i select my "random" 10 to be from the entirety of however many are present.
$randomPool = array_rand ( $butters->users->user, 10 );
I'd get the 10 random indexes, then loop through those and get the nodes.
$indexes = array();
for($i = 0; $i< 10; $i++){
$indexes[] = rand(0, $butters->users->length);
}
foreach($indexes as $index){
$user = $butters->users->item($index);
//do whatever with $user
}
You'll need to add a check to make sure that you have not already got the index when you add it to the $indexes array.
You could put this into one command, however you may end up with duplicates (unlikely depending on the amount of elements, but possible...
for($i = 0; $i< 10; $i++){
$user = $butters->users->item(rand(0, $butters->users->length));
//do something with $user
}
Put all users in an array, shuffle it and grab the first ten items:
$users = array[];
foreach ($butters->users->user as $user) {
$users[] = &$user;
}
shuffle($users);
$tenRandomUsers = array_slice($users, 0, 10);
Maybe you can shorten the first step with just $users = (array) $butters->users->user.
Create a random object (don't know the PHP specific code) then call it and compare with 10 / (total in the set). This means you should in theory select 10%, however it could be less, and your exiting code stops it from selecting more.
Assuming you are using SimpleXML, you could use an XPath to get all the users. This will return an array and from that it should be cake.
Something like this should do:
$users = $xml->xpath('//butters/users/user');
$random = array_rand($users, 10);
Someone might want to correct me on the Xpath though. Doing it from memory
if you have some sort of strange self-implemented data structure for $users you might want to use reservior sampling -- Efficiently selecting a set of random elements from a linked list

Categories