PHP/MySQLi - Combining for and while - php

I'm attempting to combine two pages into one for simplicity, however to do so, I need to find a way to combine a for() loop from one page with a while() loop from the other page, so that they both work in the same way.
This is what they currently are:
for($i = 0; $i < $count; $i++) {
and
while($widget = $grabWidget->fetch_array()) {
As you may see, the for() loop does not loop through a MySQLi query, but rather an array of values which are identical to that of what is also in a database.
The second while() loop grabs a set of identical values from the database. However they both must stay on their current bases.
My question is, can both loops be combined into one, while still being able to loop through individual database and array elements?
Thanks in advance :)
EDIT: As requested, here are both the usages for the loops.
if($grabWidget = $db->query("SELECT * FROM editor_widgets"))
{
while($widget = $grabWidget->fetch_array())
{
$id = $core->input($widget[1]);
$coords[0] = $core->input($widget[4]);
$coords[1] = $core->input($widget[5]);
$temp = $core->input($widget[2]);
$content_out = $core->output($widget[3],true);
and
if(isset($_POST['widgets']))
{
$widget = $_POST['widgets'];
$count = count($widget);
for($i = 0; $i < $count; $i++)
{
$id = $core->input($widget[$i][0]);
$content_in = $core->input($widget[$i][1]);
$coords[0] = $core->input($widget[$i][2][0]);
$coords[1] = $core->input($widget[$i][2][1]);
$temp = $core->input($widget[$i][3]);
$content_out = $core->output($widget[$i][1],true);
The new simplified page must have the ability to loop through from either an array OR a MySQLi query. So basically, I want to use the for() loop and have it also work with MySQLi

Add an interator $i thats in while thats it.
$i=0;
while($widget = $grabWidget->fetch_array()) {
++$i;
// YOUR CODE
}

Related

using php for loop for mysqli_fetch_array

I want to use for loop instead of using the conventional while loop
Like this one (psuedo code):
$list = mysqli_fetch_array($result);
for($x = 0; $x < sizeof($list); $x++){
echo $x;
}
Is this possible?
There's no reason why you can't use a while loop. That being said, when you now use sizeof($list), you will get the number of columns selected from the query (this $list variable has as many elements as columns was selected). You will therefor attempt to loop (and ouput the count of) the number of columns you fetched.
Instead, you might want to do something like this below - fetch the number of rows based on mysqli_num_rows(), which is exactly that - the number of rows returned by the query.
for ($x = 0; $x <= mysqli_num_rows($result); $x++) {
$row = mysqli_fetch_array($result);
var_dump($row);
}
Although, the standard way - and in my opinion the best way - of doing it is via while.
while ($row = mysqli_fetch_array($result)) {
var_dump($row);
}

using list() constructer for array

I have multiple dates to calculate on database. They are fetched and stored in an array.
How can I have variables for each of the returned values, since I don't know how many of the dates are returned?
Here is what I tried so far:
$get_status = $truckerController->status($gid);
$active_days = 0;
$active_d = array();
foreach ($get_status as $trucker) {
$active_d[] = $trucker->date;
}
list($date1, $date2) = $active_d;
So what I want is to have more than two or three parameters inside list() based on the array value size. Please help me out or suggest other ways to handle this issue.
Not sure if the whole approach is correct, but you can try with something like this.
$get_status = $truckerController->status($gid);
$active_days = 0;
$active_d = array();
$i = 0;
foreach ($get_status as $trucker) {
$i++;
$active_d["date".$i] = $trucker->date;
}
extract($active_d);
http://php.net/manual/en/function.extract.php

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.

Why doesn't my loop echo for all iterations?

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

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