Question about output formatting in PHP/XHTML - php

Is there a way to only print or output 10 elements per row inside a table in PHP from an indexed array with X number of elements of type int.
Maybe some function, I have not heard of?
Or some technique that's used by professionals or beginners alike.
I will embed some code for the TR and TD; however, I was just wondering if there is something I could use to only have 10 elements per row inside of my table.
[Disclaimer: I am new to PHP, and I am just learning, so please no flamers, it really hinders the learning process when one is trying to find solutions or information, thank you.]

You can use a counter in your loop to keep track of how many <td> elements you have generated in the current row:
echo "<tr>";
$i = 0;
foreach (...)
{
if ($i++ % 10 == 0)
{
echo "</tr><tr>";
}
echo "<td></td>";
}
echo "</tr>";

I like using: foreach, array_chunk, and implode to do this. It's better than having to futz with incrementing variables. I suggest you review array basics -- it's powerful stuff.
// here's an array with integers 1 to 50, for example:
$your_array = range(1,50);
// set how many you want in each row
$per_row = 10;
print "<table cellspacing='0' cellpadding='2' border='1'>\n";
Here's the code you can drop in to replace what you have:
foreach (array_chunk($your_array, $per_row) as $set_of_numbers) {
print "<tr><td>";
print implode('</td><td>',$set_of_numbers);
print "</td></tr>\n";
}
And finish with:
print "</table>\n";
That should get you the output you describe, a set of integers in a table, with 10 items per row. Now, if the size of $your_array has a remainder when divided by 10, you may need to pad those cells for looks, but that's secondary.
Output:
<table cellspacing='0' cellpadding='2' border='1'>
<tr><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td><td>10</td></tr>
<tr><td>11</td><td>12</td><td>13</td><td>14</td><td>15</td><td>16</td><td>17</td><td>18</td><td>19</td><td>20</td></tr>
<tr><td>21</td><td>22</td><td>23</td><td>24</td><td>25</td><td>26</td><td>27</td><td>28</td><td>29</td><td>30</td></tr>
<tr><td>31</td><td>32</td><td>33</td><td>34</td><td>35</td><td>36</td><td>37</td><td>38</td><td>39</td><td>40</td></tr>
<tr><td>41</td><td>42</td><td>43</td><td>44</td><td>45</td><td>46</td><td>47</td><td>48</td><td>49</td><td>50</td></tr>
</table>

Related

set while loop to return a value when there is no value

I need a little bit of help. I am pretty new to PHP so this might be an easy one for you guys. I have a while loop that is in a table. The problem I have is when the while loop returns no value, it does not build the rest of the table so row 1 might have 13 columns and row 2 might have 11 and I have no ides how to fix it. Here is the code I am using right now. Thanks for the help.
$num = 0;
while ($r2 = oci_fetch_array(results2))
{
echo "<td>" .$r2['VARIABLE1_DESC']. ": " .$r2['VARIABLE2_COMMENT']. "</td>";
$num++;
}
for (i=6; $i>$num; $i--);
If you knew the target number of columns, you could add a loop after the while to build $target - $num <td> elements. Some ideas to determine the a target:
pick an arbitrary target
execute a sql to determine the max number of rows results2 is
going to fetch.

Need help removing duplicate columns in a mysql result

I have a website that returns results by country. There is a query that returns this, then I use a loop to output the data. The only problem is that for one of these, there is a sub-50 column and the results are the same all the way to the sub-36 column. I need help removing the duplicate columns.
// By country
// sort countries by most subXs in descending order
arsort($country_sub{$dsub});
// print results
echo "<b><span style='font-size:20px;'>By Country</span></b>";
echo "<table><tr style='font-weight:bold;'><td style='width:100px;'>Country</td><td>sub".$dsub."</td>";
for($i=$dsub-1; $i>=$x; $i--){ echo "<td>sub".$i."</td>"; }
echo "</tr>";
foreach($country_sub{$dsub} as $country => $value){
echo "<tr><td>".$country."</td><td>".$value."</td>";
for($i=$dsub-1; $i>=$x; $i--){
if (isset($country_sub{$i}[$country])) {
echo "<td>".$country_sub{$i}[$country]."</td>";
} else{
echo "<td></td>";
}
echo "</tr>";
}
echo "</table><br/>";
The array $country_sub{$dsub} contains the number of people with that result or less. The foreach loop is what outputs the top numbers, and the for loop is what outputs the results itself.
You can see where this code is used at this link: http://cubingstats.netau.net/3bld/index.php. It's used in the "By Country" section. All I want is in that table, to show sub 36 and sub 27 (the ones listed above). Any help is extremely useful!
EDIT: Lines 26-32 (see comments below for link) show the addOne function, which is what adds it to the array. This is then used on lines 48-50 and 68-70 as the results are displayed.
In your SQL query, add DISTINCT just after the SELECT
SELECT DISTINCT fields,fields...fields
FROM...

How to put to style two foreach statements output PHP

How do I put the first foreach statement's output in one column in a table and the other foreach statement's output in another column. I tried something but it put it all in one column for some reason. Here is my code:
<table border="0" align="center">
<?php
foreach($anchors as $a) {
$text = $a->nodeValue;
$href = $a->getAttribute('href');
$i++;
if ($i > 16) {
if (strpos($text, "by owner") === false) {
if (strpos($text, "map") === false) {
echo "<tr><td><a href =' ".$href." '>".$text."</a><br/></td></tr>";
}
}
}
foreach($span as $s) {
echo "<tr><td>".$s->nodeValue."</td></tr>";
}
}
?>
</table>
<tr></tr> marks a row. <td></td> marks a column. To make 2 columns, use just one set of <tr> tags per iteration, with two sets of <td></td>s between them.
That said, what exactly is $span? Does it contain the same number of elements as $anchors, and you want to display one item from each per row? If so you'll need to restructure your code a bit. There are several ways to do this—here's a simple way:
<table border="0" align="center">
<?php
$i = 0;
foreach($anchors as $a) {
echo "<tr>";
$text = $a->nodeValue;
$href = $a->getAttribute('href');
if ($i >= 16) {
if (strpos($text, "by owner") === false) {
if (strpos($text, "map") === false) {
echo "<td><a href =' ".$href." '>".$text."</a><br/></td>";
}
}
} else {
echo "<td></td>"; #output a blank cell in the first column
}
echo "<td>" . $span[$i]->nodeValue . "</td>";
echo "</tr>";
++$i
}
?>
</table>
EDIT: It looks like your $span is a DOMNodeList object, not an array. I don't have experience with this, but it looks like you can use the DOMNodelist::item function to get the current item in the list (see http://php.net/manual/en/domnodelist.item.php):
echo "<td>" . $span->item($i)->nodeValue . "</td>";
So try changing the respective line in my answer to that.
It is hard without an idea of the data, but something like this perhaps:
// start a table
echo '<table>';
// for as long as there are elements in both span and anchors
for ($i=0; $i < $anchors->length && $i < $span->length; $i++) {
// start a new table row
echo '<tr>';
// get the current span and anchor
$a = $anchors->item($i);
$s = $span->item($i);
// print them
$text = $a->nodeValue;
$href = $a->getAttribute('href');
// col 1, number
echo '<td>'.$i.'</td>';
// col 2, anchor
echo '<td>'.$text.'</td>';
// col 3, span
echo '<td>'.$s->nodeValue.'</td>';
// close the table row
echo '</tr>';
}
// close the table
echo '</table>';
(code not tested) It is difficult to be more specific without the actual data.
This uses the 'current' and 'next' built in to php.
A few hints/remarks/sidenotes that may help you on the way:
- Note that I used single quotes cause they are much better for
performance (double quotes will be interpreted by php).
- Try to use as little loops (for, while, foreach) as possible. They are a powerfull
tool, but can drain memory and performance quickly!
- Only nest loops if you are working with multiple dimensions (array inside array),
which is not the case here (I think)
- Try to limit the number of nested blocks (if inside if inside if inside loop). I try to go never deeper then 2 levels (which is not an absolute rule off course, just a good standard). If not possible create a function.
- Comment your code! I have difficulty understanding your code (and I write PHP daily for a living), and I can imagine you will to in a couple of weeks. Commenting may look like a waste of time, but it will ease debugging a lot, and is a blessing when updating your (or someone elses) code later on!
EDIT:
I just noticed you are not working with a DOMNodeList and not an array, so I updated my code. Should work fine, and a lot cleaner code imo. Like I said, hard without seeing the data...

Print multiple arrays into html table

I have two arrays built from an XML response to an api. One array gives me the product info form one store and the other array gives me just the stock level in another. It looks like this:
foreach($filteredStock as $t=>$k){
$codeFirst[] = $k['code'];
echo '<tr><td>'.$t;
echo '</td><td>'.$k['desc'];
echo '</td><td>'.$k['family'];
echo '</td><td>'.$_POST['filterSelect'];
echo '</td><td>'.$k['onOrder'];
echo '</td><td>'.$k['cost'];
echo '</td><td>'.$k['sell'];
echo '</td><td>'.$k['invStore'];
echo '</td>';
}
$output = array();
$result = array_intersect_key($mainArray, array_flip($codeFirst));
foreach($result as $results=>$rValues){
echo '<td>'.$rValues['inv'];
echo '</td>';
echo '</tr>';
}
I want to display it so that it looks like this in the table:
code / desc / family / filteredClass / onOrder / cost / sell / invStore / invwarehouse
Because I need the second foreach loop to grab the values of the second array it causes a problem trying to get it to repeat on each line with the other array. Any suggestions?
Rather than echoing output each time the loop iterates, why don't you build up the table how you want it and then output it when you have it arranged properly?
It's not clear to me from the code exactly what you are trying to do, but if it's an organisation problem then why don't you store the values in seperate arrays and then combine then and arrange them appropriately before outputting them?
Using echo immediately for each loop iteration limits your options somewhat.

limiting array results returned

Hi I would like to limit the results returned depending on what type of product a user selects, $r[1] is the type of product with the array:
foreach($list as $r)
{
$row_color = ($row_count % 2) ? $color1 : $color2;
$size2 = $r[2];
echo "<tr>
<td id=\"id\"><span id=\"non_sorting_header\">" .$r[0]. "</span></td>
<td id=\"name\"><span id=\"non_sorting_header\">" .$r[1]. "</span></td>
<td id=\"speed\"><span id=\"sorting_header\">" .kMGTB2($size2). "</span></td>
<td id=\"download\"><span id=\"sorting_header\">" .$r[3]. " Gb<br />per month</span></td>
<td id=\"contract\"><span id=\"sorting_header\">1<br />month</span></td>
<td id=\"info\"><span id=\"non_sorting_header\">".$r[5]."</span></td>
<td id=\"buy\"><span id=\"non_sorting_header\">".$r[4]."<br />".$r[6]."</span></td>
</tr>";
$row_count++;
}
So if the user enters 'banana' then the function will find all instances within the array where $r[1] starts with the word 'banana' - start is key as it could be 'banana 1' 'banana 2' etc....
I cannot figure out a slick way to do this...any help would be appreciated!
You could use something like the following
function selectFromArray($prefix="", $productArray=array()) {
return array_filter($productArray,
create_function('$element',
'return (stripos($element[1],"'.$prefix.'") === 0); '));
}
Used like:
$list = selectFromArray("Banana", $list);
then proceed with the rest of your page.
That said, it's usually better to do this kind of filtering in your sql query with a WHERE clause
I'm not sure if Jonathan's answer is really the best way to do this.
First of all, create_function() is best avoided. Even without that, though, when using a separate function for it, you're still looping through the list twice. First you loop through the entire list to filter it, and then you loop through the filtered list to print the details. You can easily combine those two:
foreach ($list as $r)
{
if (stripos($r[1], $prefix) === 0) {
continue;
}
// as before...
}
If that condition gets any more complicated you can of course split it out into a separate function as well.

Categories