PHP: Troubles on indexing a nested for-loop - php

I am trying to print a 3-dimensional array into a table. But the indexes are kinda fked up. When I use the following (psuedo)code:
...
<<print headers and stuff>>
for ( $i = 0; $i < count( $array ); i++) {
$itemArray = $array[i];
for ( $j = 0; $j < count( $itemArray; j++) {
$innerItem = $itemArray[j];
echo <<tr start + both indexes in td>>
foreach ($innerItem as $spec) {
echo <<td with item>>
}
echo <<tr stop>>
}
}
In this example I am using i as index for the outer array and j as an index for the inner array (pretty obvious).
The result I am getting from this is as follows:
| index i | index j | title1 | title2 |
| 0 | 0 | | |
| 1 | 0 | | |
| 2 | 0 | | |
| ... | ... | | |
Whilst I would expect:
| index i | index j | title1 | title2 |
| 0 | 0 | | |
| 0 | 1 | | |
| 1 | 0 | | |
| 1 | 1 | | |
| 1 | 2 | | |
| 2 | 0 | | |
| ... | ... | | |
The (original) full code is:
echo "<h1>Combat analysis</h1>";
echo '<table cellspacing="0" cellpadding="4" border="1"><tbody>';
echo "<tr><td>#Mon</td><td>#Att</td><td>DungLVL</td><td>CharLVL</td><td>Health</td><td>Weapon</td><td>No. potions</td></tr>";
for ($battleIndex = 0; $battleIndex < count($this->combatLog); $battleIndex++) {
$battle = $this->combatLog[$battleIndex];
for ($attackIndex = 0; $attackIndex < sizeof($battle); $attackIndex++) {
$attack = $battle[$attackIndex];
echo "<tr><td>" . $battleIndex . "</td><td>" . $attackIndex . "</td>";
foreach ($attack as $stat) {
echo "<td>" . $stat . "</td>";
}
echo "</tr>";
}
}
echo "</tbody></table>";
What is going wrong?

Tested your code and runs as expected. You should do a echo '<pre>'.print_r($this->combatLog).'</pre>'; and debug the array contents.
Also I would recommend you the following:
1) You can use foreach instead of for, example: foreach ($this->combatLog as $battleIndex => $battle)
2) If you're not sure that a array contains values you should first do a: if (is_array($this->combatLog) && count($this->combatLog) > 0)
3) For simplicity and code maintenance I would first loop the multi-dimensional array and turn it into a one dimension called $attacks containing a array per each attack indexed by keys that you can recognize, ej:
$attacks=array();
$attacks[]=array(
'Mon'=>$battleIndex,
'Att'=>$attackIndex,
'DungLVL'=>isset($stat[0])?$stat[0]:null,
'CharLVL'=>isset($stat[1])?$stat[1]:null,
'Health'=>isset($stat[2])?$stat[2]:null,
'Weapon'=>isset($stat[3])?$stat[3]:null,
'Potions'=>isset($stat[4])?$stat[4]:null,
);
Then you could define some columns for example:
$columns=array(
'Mon',
'Att',
'DungLVL',
'CharLVL',
'Health',
'Weapon',
'Potions',
);
Then print the table header like this:
echo '<tr>';
foreach ($columns as $column) {
echo '<td>'.$column.'</td>';
}
echo '</tr>';
And print rows like this:
foreach ($attacks as $attack) {
echo '<tr>';
foreach ($columns as $column) {
echo '<td>'.$attack[$column].'</td>';
}
echo '</tr>';
}

Related

Displays the data array in the default table with looping

I have 1 array data may also be more and want to present it on the table, I tried to make the default table by 5 column, but when I try the same result 5 column all its data. should have 3 column 2 column is empty, what is lacking in my script?
This myscript
<?php
$no = 1;
for($x=1; $x<=5; $x++) {
foreach ($mydata as $row) {
echo '<tr>';
echo '<td>'.$no.'</td>';
echo '<td>'.$row->id.'</td>';
echo '<td>'.$row->name.'</td>';
echo '<td>'.$row->class.'</td>';
echo '</tr>';
$no++;
}
}
?>
the results of the script
NO | ID | NAME | ClASS |
____|____ |______|_______|
1 | 001 | Paul | x |
2 | 001 | Paul | x |
3 | 001 | Paul | x |
4 | 001 | Paul | x |
5 | 001 | Paul | x |
I expected
NO | ID | NAME | ClASS |
____|____ |______|_______|
1 | 001 | Paul | x |
2 | | | |
3 | | | |
4 | | | |
5 | | | |
Try this:
<?php
$no = 1;
for ($x=1; $x <= 5; $x++) {
if (isset($mydata[$x-1])) {
$row = $mydata[$x-1];
echo '<tr>';
echo '<td>'.$no.'</td>';
echo '<td>'.$row->id.'</td>';
echo '<td>'.$row->name.'</td>';
echo '<td>'.$row->class.'</td>';
echo '</tr>';
} else {
echo '<tr>';
echo '<td>'.$no.'</td>';
echo '<td></td>';
echo '<td></td>';
echo '<td></td>';
echo '</tr>';
}
$no++;
}
?>
You need to check if the data is set based off $x var and then render empty row or populated.
You don't need nested loops. Just a single loop from 1 to 5, and each iteration shows the corresponding element of the array, or empty cells if there's no such element.
for ($x = 1; $x <= 5; $x++) {
echo "<tr>";
echo "<td>" . $x . "<td>";
if (isset($mydata[$x-1])) {
$row = $mydata[$x-1];
echo '<td>'.$row->id.'</td>';
echo '<td>'.$row->name.'</td>';
echo '<td>'.$row->class.'</td>';
} else { // show empty fields
echo "<td></td><td></td><td></td>";
}
echo "</tr>";
}
There's also no need for separate variables $x and $no.

PHP mysqli fetch_row - iterate over multiple records

I have been messing with this for 3 days now, researching and experimenting: it's time to ask for some help.
I have a bit of code for a schedule display page that loops over a database table, once per appointment type. It gathers all appointments of that type for the week, and returns them in a row, like this:
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| Name | Year | Mon | Tue | Wed | Thu | Fri | Sat | Sun | Purp |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| IST | NA | 9-4 | | | | | | | ABC |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| OT | NA | | 8-2 | 8-2 | 8-2 | 8-2 | | | DEF |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
My code works exactly as I want it to, with one fatal flaw. If there's more than one row for a "Name", I get this as my row:
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| Name | Year | Mon | Tue | Wed | Thu | Fri | Sat | Sun | Purp |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| IST | NA | 9-4 | | | | | | | ABC |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+
| OT | NA | | 8-2 | 8-2 | 8-2 | 8-2 | | | DEF |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+-+-----+-+-+-+-+-+-----+
| MTG | | 1-2 | | | | | | | | | 1-2 | | | | | | GHI |
| | | | | | | | | | | | | | | | | | JKL |
+------+------+-----+-----+-----+-----+-----+-----+-----+------+-+-----+-+-+-+-+-+-----+
So instead of inserting into the appropriate <td>, it makes a whole new set of them. It's really frustrating because I'm sure it's something simple, but I can't see it... :(
Code:
$apptnamestop = array("IST", "OT", "MTG", "TR-CN", "EVENT", "EN", "REC", "TO");
$daysofweek = array("1", "2", "3", "4", "5", "6", "0");
foreach ( $apptnamestop as $name) {
print str_repeat($tab, 8) . "<tr>\n";
print str_repeat($tab, 9) . "<td class=\"td1s\">$name</td>\n";
print str_repeat($tab, 9) . "<td class=\"td1s\">N/A</td>\n";
$getdataquery = "SELECT appointmentName as name
, appointmentType as type, appointmentStartDateTime as sdt
, appointmentEndDateTime as edt, appointmentPurpose as purp
from tblAppointments
where appointmentStaffIDsToAttend like '%{$_SESSION['user_id']}%'
and appointmentName = '$name'
and (appointmentStartDateTime >= DATE_ADD(CURDATE(), INTERVAL (9 - IF(DAYOFWEEK(CURDATE())=1, 8, DAYOFWEEK(CURDATE()))) DAY)
and appointmentEndDateTime < DATE_ADD(CURDATE(), INTERVAL (16 - IF(DAYOFWEEK(CURDATE())=1, 8, DAYOFWEEK(CURDATE()))) DAY))
";
$getdataqueryresults = $mysqli->query($getdataquery)
or trigger_error("<p class=\"error\">We're very sorry, but an error has occurred when interacting with the CHAIRS database. Please try again and see if the error repeats. If it does, please get the following information in its entirety to your database adminapptrator so the CHAIRS developer can get the error resolved.<br />Error Message: " . $mysqli->error, E_USER_ERROR);
$datarowcnt = $getdataqueryresults->num_rows;
if ($datarowcnt > 0) {
while ($row = $getdataqueryresults->fetch_row()) {
$rows[] = $row;
}
foreach ($rows as $row) {
$title = $row[0];
$type = $row[1];
$sdt = $row[2];
$edt = $row[3];
$purp = $row[4];
$c=7;
if ($type == 1) {
$typew = "Mandatory";
} else {
$typew = "Elective";
}
$sparts = explode(" ", $sdt);
$eparts = explode(" ", $edt);
$tdiff = getTimeDiff($sparts[1], $eparts[1]);
foreach ($daysofweek as $day) {
if ($title == $name) {
if ($day == date('w', strtotime("$sparts[0]"))) {
if ($sparts[0] == $eparts[0]) {
print str_repeat($tab, 9) . "<td class=\"td1s\">$sparts[1] - $eparts[1]<br />($tdiff) - $typew</td>\n";
$c--;
} else {
$s = strtotime("$sparts[0]");
$e = strtotime("$eparts[0]");
for ($i=$s; $i<=$e; $i+=86400) {
print str_repeat($tab, 9) . "<td class=\"td1s\">$sparts[1] - $eparts[1]<br />($tdiff) - $typew</td>\n";
$c--;
}
}
}
if ( $c > 0) {
$c--;
print str_repeat($tab, 9) . "<td class=\"td1s\"></td>\n";
}
}
}
}
$rc++;
} else {
foreach ($daysofweek as $day) {
print str_repeat($tab, 9) . "<td class=\"td1s\"></td>\n";
}
}
print str_repeat($tab, 9) . "<td class=\"td1s\">$purp</td>\n";
$purp = "";
print "</tr>\n";
}
The new rows are started here:
foreach ( $apptnamestop as $name) {
print str_repeat($tab, 8) . "<tr>\n";
print str_repeat($tab, 9) . "<td class=\"td1s\">$name</td>\n";
As you can see, this new row is started once per element in $apptnamestop, rather than once per row from the database. The code doesn't care how many matching rows it finds in the table, it is only going to insert one new tr per name.
There are a couple of ways to improve this situation, depending on your needs.
If you need to always insert a row per name, regardless of whether there is a matching row in the database, keep lines 4, 5 and 6 the same as they are now. We will need to modify the inner loop (foreach ($rows as $row)) to output the new table rows for every loop beyond the first one:
$rowCounter = 0;
foreach ($rows as $row) {
if ($rowCounter > 0) {
print "</tr>\n"; // Close the previous table row
print str_repeat($tab, 8) . "<tr>\n";
print str_repeat($tab, 9) . "<td class=\"td1s\">$name</td>\n";
print str_repeat($tab, 9) . "<td class=\"td1s\">N/A</td>\n";
}
$rowCounter++;
// Remainder of the loop code goes here
...
}
If you prefer to skip creation of the table row when no matching database row is found, move the row creation statements into the inner loop entirely; this way it will run only if database rows are found.
As a final note, consider implementing a view templating system; by separating your logic code from your display code, you can easily modify either one without breaking the other. Your code becomes much simpler to read and modify in the future.

how to display data in two column with php with header

I have database
---------------------------------------------
no | name | code | grade
---------------------------------------------
1 | john | A1 | C
2 | john | A2 | D
3 | john | A3 | B
4 | tom | A1 | A
5 | john | A4 | A
6 | alice | A1 | C
7 | alice | A2 | D
8 | john | A5 | D
9 | john | A6 | C
---------------------------------------------
when I want show data with name john, I want result with 2 column:
---------------------------------------------------------------
no | name | code | grade | no | name | code | grade |
---------------------------------------------------------------
1 | john | A1 | C | 5 | john | A5 | D |
2 | john | A2 | D | 6 | john | A6 | C |
3 | john | A3 | B | | | | |
4 | john | A4 | A | | | | |
---------------------------------------------------------------
this my code that I already try
$result = mysql_query("select * from grade ");
echo "<table border='1'><tr>";
echo "<td>no</td>";
echo "<td>name</td>";
echo "<td>code</td>";
echo "<td>grade</td></tr><tr>";
$no = 1;
$count = 1;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
extract($row);
echo "<td>$no</td>";
echo "<td>$row[name]</td>";
echo "<td>$row[code]</td>";
echo "<td>$row[grade]</td>";
if ($count++ % 2 == 0)
{
echo "</tr><tr>";
$no++;
}
}
echo "</tr></table>";
But the result not what I want, this is the result when I run my code
no | name | code | grade | | | | |
---------------------------------------------------------------
1 | john | A1 | C | 1 | john | A4 | A |
2 | john | A2 | D | 2 | john | A5 | D |
3 | john | A3 | B | 3 | john | A6 | C |
---------------------------------------------------------------
Can somebody help me...thank you
This is representation problem, so it can be solved it two ways.
1. You can make this columns using modern HTML:
<section style="-webkit-column-count:2; -webkit-column-gap:15;">
<div class='columns'>
<table>
<tr>
<th>no</th>
<th>name</th>
<th>code</th>
<th>grade</th>
</tr>
<?php
$result = mysql_query("select * from grade ");
$no = 1;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
echo '<tr>';
echo "<td>{$row['no']}</td>";
echo "<td>{$row['name']}</td>";
echo "<td>{$row['code']}</td>";
echo "<td>{$row['grade']}</td>";
echo '</tr>';
$no++;
}
?>
</table>
</div>
</section>
2. If you want to stick to plain tables, you have to do some calculations:
First, you need to know full amount of grades you gonna show. You can get it with SQL query(more efficient way), I'll do it by preloading all data to array. HTML footer and header are omitted for brevity.
<?php
$data = array();
$result = mysql_query('SELECT * FROM grade;');
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$data[] = $row;
}
$rows = (int) ceil(count($data)/2);
for ($i=0; $i < $rows; $i++) {
$no = $i + 1;
echo '<tr>';
echo "<td>{$no}</td>";
echo "<td>{$data[$i]['name']}</td>";
echo "<td>{$data[$i]['code']}</td>";
echo "<td>{$data[$i]['grade']}</td>";
if (array_key_exists($i + $rows, $data)) {
$no = $i + $rows + 1;
echo "<td>{$no}</td>";
echo "<td>{$data[$i + $rows]['name']}</td>";
echo "<td>{$data[$i + $rows]['code']}</td>";
echo "<td>{$data[$i + $rows]['grade']}</td>";
} else {
echo "<td> </td>";
echo "<td> </td>";
echo "<td> </td>";
echo "<td> </td>";
}
echo "</tr>\n";
}
I have not tested this nor checked for errors, but I think it is on the lines of what you are trying to accomplish.
$result = mysql_query("select * from grade ");
$orig_count = mysql_num_rows($result);
if ( $orig_count % 2 != 0 )
$count = $orig_count + 1;
$cols = $count / 2;
//draw header
echo "<table border='1'><tr>";
echo "<td>no</td>";
echo "<td>name</td>";
echo "<td>code</td>";
echo "<td>grade</td></tr><tr>"
for ( $i = 0; $i < $cols; i++ )
{
if ( $orig_count == 0 )
break; //zero results
//first column
echo "<td>$i</td>";
echo "<td>".mysql_result( $result, $i, "name" )."</td>";
echo "<td>".mysql_result( $result, $i, "code" )."</td>";
echo "<td>".mysql_result( $result, $i, "grade" )."</td>";
//second column
if ( $i > $orig_count )
{
echo "<td> </td>";
echo "<td> </td>";
echo "<td> </td>";
echo "<td> </td>";
}
else
{
echo "<td>".$i+($count/2)."</td>";
echo "<td>".mysql_result( $result, $i+($count/2), "name" )."</td>";
echo "<td>".mysql_result( $result, $i+($count/2), "code" )."</td>";
echo "<td>".mysql_result( $result, $i+($count/2), "grade" )."</td>";
}
}
//finish off
echo "</tr></table>";

Coordinates from MySQL to HTML table (PHP, PDO, MySQL)

I am creating game which uses MySQL database to create "playing field".
In my MySQL table I have two columns pointX and pointY, both INT. I could also use POINT, but in my case these two columns are better solution.
| id | pointX | pointY | player | game |
|----|--------|--------|--------|------|
| 1 | -2 | 1 | 7 | 10 |
| 2 | -3 | 2 | 5 | 10 |
| 3 | 2 | -2 | 2 | 10 |
| 4 | -2 | -1 | 1 | 10 |
I should produce HTML table from this MySQL table. Something like this, but with no coordinateheaders (below those are only for easier understanding):
|-----|----|----|----|----|----|----|
| Y/X | -3 | -2 | -1 | 0 | 1 | 2 |
|-----|----|----|----|----|----|----|
| -2 | | | | | | 2 |
|-----|----|----|----|----|----|----|
| -1 | | 1 | | | | |
|-----|----|----|----|----|----|----|
| 0 | | | | | | |
|-----|----|----|----|----|----|----|
| 1 | | 7 | | | | |
|-----|----|----|----|----|----|----|
| 2 | 5 | | | | | |
|-----|----|----|----|----|----|----|
Plus.. every <td> should have attribute data-cell, which includes coordinates, as example data-cell="-2x-1".
What is the best way to get started?
$rng = $dbh->prepare('
SELECT MIN(pointX) AS minX, MIN(pointY) AS minY,
MAX(pointX) AS maxX, MAX(pointY) AS maxY
FROM field
WHERE game = ?
LOCK IN SHARE MODE
');
$qry = $dbh->prepare('
SELECT pointX, pointY, player
FROM field
WHERE game = ?
ORDER BY pointX, pointY
');
$dbh->beginTransaction();
$rng->execute([$game_id]);
$qry->execute([$game_id]);
$dbh->rollBack();
$limits = $rng->fetch();
$player = $qry->fetch();
echo '<table>';
for ($y = $limits['minY']; $y <= $limits['maxY']; $y++) {
echo '<tr>';
for ($x = $limits['minX']; $x <= $limits['maxX']; $x++) {
printf('<td data-cell="%dx%+dy">', $x, $y);
if ($player and $player['pointX'] == $x and $player['pointY'] == $y) {
echo htmlentities($player['player']);
$player = $qry->fetch();
} else {
echo ' ';
}
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
It looks like you are already off to a good start. Assuming the number of cells for X and Y as $xcells and $ycells, the next step I would take is to build your table like so:
echo "<table>";
for ($i = -3; $i < $ycells; i++) {
echo "<tr>";
for ($j = -3; $j < $xcells; j++) {
echo "<td data-cell='" . $i . "y" . $j . "x'>";
}
echo "</tr>";
}
echo "</table>";

PHP display images from column value

Table
+-----+--------+---------+
| ID | Name | Images |
+-----+--------+---------+
| 001 | John | 5 |
| 002 | Mark | 3 |
+-----+--------+---------+
i would like to display like this
Jon, 001-1.jpg | 001-2.jpg | 001-2.jpg | 001-3.jpg | 001-4.jpg | 001-5.jpg |
Mark, 002-1.jpg | 002-2.jpg | 002-2.jpg | 002-3.jpg |
the images value on database table will be the number of images return to create images link
You can use this though. Didn't know why you found it difficult.
$c = 0
while (false !== ($data = fetch_array_as_row_function()))
{
echo "<tr>";
echo "<td>", $data["name"], "</td>";
for ($i = 0; $i < $data["images"]; $i++)
echo "<td>00", $c,"-", $i, "</td>";
echo "</tr>";
}
Here, the function fetch_array_as_row_function() is something equivalent to what mysql_fetch_array() does.

Categories