table + foreach - new column? - php

<?php
$values = array();
for($i=0;$i<100;$i++){
$values[$i] = "aaa" . $i;
} ?>
<table>
<?php
foreach ($values as $i => $val) {
echo "<tr><td>" . $val . "</td> </tr>";
} ?>
</table>
this generated me:
aaa1
aaa2
...
aaa50
...
aaa90
...
aaa100
how can I make two column?
aaa1 aaa50
aaa2 ....
... aaa90
aaa50 aaa100
but no:
aaa1 aaa2
aaa3 aaa4
... ....
aaa99 aaa100

a function
function sqlArr($sql){
$ret = array();
$res = mysql_query($sql) or trigger_error(mysql_error()." ".$sql);
if ($res) {
while($row = mysql_fetch_array($res)){
$ret[] = $row;
}
}
return $ret;
}
a code
$temp = sqlArr("SELECT value FROM table");
$data = array();
for($i=0;$i<50;$i++){
$data[] = array($temp[$i],$temp[$i+50]);
}
unset($temp);
a template
<table border='1'>
<? foreach ($data as $i => $row): ?>
<tr>
<? foreach ($row as $cell): ?>
<td><?=$cell?></td>
<? endforeach ?>
</tr>
<? endforeach ?>
</table>

Try if this works for you. Regardless of the format of the items contained in $values, it should print the array the way you want.
<?php
$size = count($values);
$halfSize = intval(ceil($size / 2));
for ($i = 0; $i < $halfSize; $i++)
{
$j = $i + $halfSize;
echo "<tr><td>" . $values[$i] . "</td>";
// If $size is odd, $halfSize is rounded up. This means that if we have
// 3 elements, it will try to access to $values[3], since $halfSize would
// be 2. The last second column element should be blank in this case.
// So, if $halfSize is odd, and $i is the last element, don't print an
// additional table cell.
if (!($i == $halfSize - 1 && $size % 2 == 1))
echo "<td>" . $values[$j] . "</td>";
echo "</tr>";
}
?>

The way that I would do this is to create two separate tables (each one column wide) and then include both of them in a single, two-columned table:
<?php
$list=array('a','b','c','d','e','f');
$midpoint=floor(count($list)/2);
$tableHeader='<table width="100%">';
$tableFooter='</table>';
$leftTable=$tableHeader;
$rightTable=$tableHeader;
for ($c=0; $c<$midpoint; $c++)
{
$leftTable.='<tr><td width="100%">'.$list[$c].'</td></tr>';
}
$leftTable.=$tableFooter;
for ($c=$midpoint; $c<count($list); $c++)
{
$rightTable.='<tr><td width="100%">'.$list[$c].'</td></tr>';
}
$rightTable.=$tableFooter;
$mainTable='<table><tr><td width="50%">'.$leftTable.'</td><td width="50%">'.$rightTable.'</td></tr></table>';
echo $mainTable;
?>
Add some CSS to remove padding around the sub-tables and borders etc and you should be good to go.

Since you already numbered it, just abstract it down:
a1 a51
a2 a52
...
a49 a99
a50 a100
is exactly the same as
a1 a1+50
a2 a2+50
...
a50 a50+50
This makes you having the following code:
echo "<table>";
for($i=1; $i<=50; $i++) {
echo "<tr><td>" . $i . "</td><td>" . ($i+50) . "</td></tr>";
}
echo "</table>";
Note: This requires you to let the table be generated this way. If it's actually not numbered like that, you would have to figure out another way to generate the abstract table in my listing 2 (just think about the index the entries have in relation to their left neighbor).

Related

Filling table in a specific way with sql data using loops

I want to put data from the following database table in a html table in a specific way.
Below is my php code:
echo "<table style='border:2px solid black;width:100%;'>";
foreach ($results as $key => $value) {
for ($i = 1; $i < 4; $i++) { // 3 + 1 = 4 (itération sur la valeur de $value['ligne'])
if ($i == $value['ligne']) {
echo "<tr>";
for ($j = 1; $j < 4; $j++) { // itération sur la valeur de $value['colonne']
//if ($j == $value['colonne'] ) {
echo "<td style='padding:1em;border:1px solid black;'>".$value['contenu']."</td>";
//}
}
echo "</tr>";
}
}
}
echo "</table>";
And here is the output that i'm having:
What I want to achieve is having "colonne1" only in the column 1 of the table; "colonne2" only in column 2, etc. In the same way, "Ligne1" should appear only in row 1; "Ligne2" in row 2, which is what i've been able to do. Any idea? Thanks, in advance.
You can use a two dimensional array to achieve the object seeing you’re looking for.
First, build a data structure from the database results.
// assuming you’ve retrieved table into $results
$table =array();
foreach($results as $v) {
$row = $v[‘ligne’];
$col = $v[‘colonne’];
$content = $v[‘contenue’];
$table[$row][$col] = $content;
}
// build html table
?>
Then you can print it out in the view:
<table>
<?php foreach($table as $row_array): ?>
<tr>
<?php foreach($row_array as $col): ?>
<td><?= $col ?></td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</table>

Return loop output to table (PHP)

I'm probably making a very basic error but I'm quite new to this.
I have a table where I need to edit what is displayed in each box using variables but I'm having trouble with getting the outputs into the table. Experimentation helped me work out the first box but I can't get the second one working because I think the function is written incorrectly. I need a conditional loop that displays all even numbers between 10 and 20 (the code below doesn't have anything to do with even numbers at the moment I'm just trying to get it to work)
<?php
$random = rand() . srand(3034);
function loop() {
for ($i = 10; $i <= 20; $i++) {
$loop = $i;
return $loop;
}
}
echo "<table border='1'>
<tr>
<td>Box 1 - ".$random."</td>
<td>Box 2 - ".$loop."</td>
</tr>
</table> ";
?>
Any help is much appreciated.
You need to loop on the tags itself, because the return condition in the loop breaks it to only 1 iteration.
So you should do it like this:
echo "<tr>
<td>Box 1 - ".$random."</td>";
for ($i = 10; $i <= 20; $i++) {
echo "<td>Box 2 - ".$i."</td>";
}
echo"</tr>";
Additionally to my comment here is some more code:
<?php
$random = rand() . srand(3034);
function loop($randomNumber) {
for ($loop = 10; $loop <= 20; $loop++) {
echo
'<tr>' .
'<td>Box 1 - ' . $randomNumber . '</td>' .
'<td>Box 2 - ' . $loop . '</td>' .
'</tr>';
}
}
echo
'<table border="1">' .
loop($random) .
'</table>';
Try this:
<?php
function loop(){
$return = '';
for($i = 10; $i <=20; $i++){
$random = rand() . srand(3034);
if($i%2==0){
$return.='<tr>
<td>Box 1 - '.$random.'</td>
<td>Box 2 - '.$i.'</td>
</tr>';
}
}
return $return;
}
echo '<table>'.loop().'</table>';

Distinguish between elements and last element of array

Im creating tablerows based on the number of the array colours:
$query = mysql_query("SELECT * FROM things);
$num = mysql_num_rows($query );
$colours = array ();
if($num)
{
for ($i = 0; ($row = mysql_fetch_assoc($query)); ++$i)
{
$colours[$i] = $row["colours"];
}
}
$arrlength = count($colours);
for ($i = 0; ($i < ($arrlength)); ++$i){
echo "
<tr class='border_bottom'><td>".$colours[$i]."</td></tr>
";
}
So, if colours is, lets say, equal to 8, 8 table rows with the class border_bottom are created.
border_bottom is used by CSS to add a border to the bottom of each tablerow.
What I need is some PHP help: I need code which checks the array colours. The last element of the array has to go with an empty id since I dont want a border-bottom added to that very last tablerow. All other tablerows have to go with the border_bottom class, tho.
I was thinking of starting the code like that:
echo"
<tr class='
";
-->PHP code goes here<--
echo"
'>
<td>".$colours[$i]."</td></tr>
Try this:
<?php
$query = mysql_query("SELECT * FROM things");
$num = mysql_num_rows($query);
$colours = array();
if($num)
{
while($row = mysql_fetch_assoc($query))
{
$colours[] = $row["colours"];
}
}
$arrlength = count($colours);
for ($i = 0; $i < $arrlength; ++$i){
if($i < $arrlength - 1){
echo "<tr class='border_bottom'><td>{$colours[$i]}</td></tr>";
}else{
echo "<tr><td>{$someColor}</td></tr>";
}
}
Try the following code in your table row echo
echo "<tr"
.($i < $arrlength - 1 ? " class='border_bottom'" : "")
.">"
."<td>{$colours[$i]}</td></tr>";
You can actually do this while fetching the rows without needing to count how many there are, by reading ahead one row.
$previous_row = mysql_fetch_array(); // fetch the first row (if there is one)
while ($previous_row) {
if ($row = mysql_fetch_array()) {
// if another row is fetched, then the previous row was NOT the last row
echo '<tr class="border_bottom"><td>' . $previous_row['colours'] . '</td></tr>';
} else {
// otherwise, the previous row WAS the last row, and does not get the class
echo '<tr><td>' . $previous_row['colours'] . '</td></tr>';
}
$previous_row = $row; // Set the previous row to the current row
}

Echo out SQL result to create a timetable

I am having problems printing out a timetable using the results from a SQL statement and some HTML layout with PHP.
I have the times of the classes along the top of the page.
I am trying to put the days of the week along the side of the page and then check if the result of the SQL statement (containing a module) should be printed in the specific day and time.
//Print out the top of the array to display the times
echo "<div><table class='table table-bordered'><thead><tr><th></th><th>9-10</th><th>10-11</th><th>11-12</th><th>12-13</th><th>13-14</th><th>14-15</th><th>15-16</th><th>16-17</th></tr></thead><tbody>'";
//Now loop through the result of the SQL statement that contains the modules associated with the selected course
while($row = mysqli_fetch_array($result1)) {
for($d = 1; $d < 6; $d++){
$printday = $days[$d];
echo "$printday";
for($t = 9; $t < 17; $t++) {
if($row['Day'] == $d && $row['Time'] == $t){ //fix this area so that it moves along
echo "<td>" . $row['ModuleName'] . "<br/>\n " .$row['Location'] . "</td>";
} //if
else {
echo "<td></td>";
} //else
} //for 2
echo "</tr>";
} //for 1
} //while
The problem is that I am printing out Monday-Friday 3 times as there are 3 $row results. Any idea how I could get this to work.
Your looping through your data in the wrong spot, you first need to put that in an array so you can loop through it for each day/time.
//Print out the top of the array to display the times
echo "<div><table class='table table-bordered'><thead><tr><th>Day</th><th>9-10</th><th>10-11</th><th>11-12</th><th>12-13</th><th>13-14</th><th>14-15</th><th>15-16</th><th>16-17</th></tr></thead><tbody>'";
//Now loop through the result of the SQL statement that contains the modules associated with the selected course
$courses = array();
while($row = mysqli_fetch_array($result1)) {
$courses[] = $row;
} //while
for($d = 1; $d < 6; $d++){
$printday = $days[$d];
echo "<tr><td>" . $printday . "</td>";
for($t = 9; $t < 17; $t++) {
unset($course_row);
foreach($courses as $course){
if($course['Day'] == $d && $course['Time'] == $t){ //fix this area so that it moves along
$course_row .= $course['ModuleName'] . "<br/>\n " .$course['Location'] . "<br/>\n<br/>\n";
} //if
}
if(isset($course_row)){
echo "<td>" . $course_row . "</td>";
} else {
echo "<td> </td>";
} //else
} //for 2
echo "</tr>";
} //for 1

PHP - put the student name and grade into suitable skill name

(1) class
(2) studentmark
(3) skill
PHP code:
<?php
//DB CONNECTION
//---(1)Get skillname---
$q = "SELECT skillName FROM skill ORDER BY skillName asc";
$r = mysqli_query($dbc, $q);
$num_rows = mysqli_num_rows($r);
while($row = mysqli_fetch_array($r, MYSQLI_ASSOC))
{
$skills[] = $row['skillName'];
}
//---(2)Get classname---
$q1 = "SELECT className FROM class";
$r1 = mysqli_query($dbc, $q1);
$num_rows1 = mysqli_num_rows($r1);
while($row1 = mysqli_fetch_array($r1, MYSQLI_ASSOC))
{
$className[] = $row1['className'];
}
//---(3)Create table---
echo '<table border="1" style="border-collapse: collapse; text-align: center">';
echo '<tr>';
for($a = 0; $a < $num_rows; $a++)
{
echo '<th colspan="2">'.$skillName[$a].'</th>';
}
echo '</tr>';
for($b = 0; $b < $num_rows; $b++)
{
echo '<th>Student Name</th>';
echo '<th>Grade</th>';
}
echo '</tr>';
//---(4)Get student name and grade---
for($s = 0; $c < $num_rows1; $c++)
{
$q2 = "SELECT GROUP_CONCAT(sm.studentName) as studentName,
GROUP_CONCAT(sm.studentGrade) as studentGrade,
s.skillName
FROM studentmark sm
LEFT JOIN skill s ON sm.skillID = s.skillID
WHERE sm.className = '".$className[$c]."'
GROUP BY s.skillID";
$r2 = mysqli_query($dbc, $q2);
$num_rows2 = mysqli_num_rows($r2);
$value = array();
while($row2 = mysqli_fetch_array($r2, MYSQLI_ASSOC))
{
$value[] = $row2;
}
echo '<tr>';
for($d = 0; $d < $num_rows2; $d++)
{
echo '<td>'.$value[$d]['studentName'].'</td>';
echo '<td>'.$value[$d]['studentGrade'].'</td>';
}
echo '</tr>';
}
echo '</table>';
?>
From above code, my output is below:
I am almost finished. I can show the student name and grade in 1 row.
Now, the last thing I want to do is put them into suitable skill name like below:
I want to compare the $skills and s.skillname on $q2.
Below is my logic:
if($value[X]['skillName'] == $skills[X])
{
//put student name and grade inside
}
else
{
//empty cell
}
But I don't know where should I open for loop and put my logic in (4). Can someone help me?
So I'm definitely messing up your nice clean code for the sake of not looping through the data multiple times. I also display the classnames cause that seems like useful info.
I changed some variable names cause I found it easier to remember what each variable was for. Also, note how the student info query is only executed once. Normaly (read: I can't think of a reason why you wouldn't but I'm CMA), you want to minimize the number of times you query the database
The code below will replace the entire script you posted.
<?php
//DB CONNECTION
$dbc = // magic connection sauce you already have
// get skills and stash how many there are
$q_class = "SELECT skillName FROM skill ORDER BY skillName asc";
$r_class = mysqli_query($dbc, $q_class);
$num_skills = mysqli_num_rows($r_class);
// start table code so that we can echo the skillname headers
echo '
<table border="1" style="border-collapse: collapse; text-align: center">
<thead>
<tr>
<th rowspan=2>Classes</th>';//header for class name column
$header = array();
while($row = mysqli_fetch_array($r_class, MYSQLI_ASSOC))
{
$skills[] = $row['skillName'];
// store both thead rows at the same time so that we can echo them out properly later
$header['first'][] = '
<th colspan="2">' . $row['skillName'] . '</th>';
$header['second'][] = '
<th>Student Name</th>
<th>Grade</th>';
}
echo '
' . implode($header['first']) . '
</tr>
<tr>' . implode($header['second']) . '
</tr>';
// clean-up
mysqli_free_result($r_class);
// get class names and stash how many there are
$classes = array();
$query_class = "SELECT className FROM class";
$r_class = mysqli_query($dbc, $query_class);
$num_classes = mysqli_num_rows($r_class);
while($row = mysqli_fetch_array($r_class, MYSQLI_ASSOC))
{
$classes[] = $row['className'];
}
// clean-up
mysqli_free_result($r_class);
echo '
</thead>
<tbody>';
// pull query out of loop so that you'll only have to execute it once.
$studentInfoQuery = "
SELECT
GROUP_CONCAT(sm.studentName) as studentName,
GROUP_CONCAT(sm.studentGrade) as studentGrade,
s.skillName,
sm.className
FROM studentmark sm
LEFT JOIN skill s ON sm.skillID = s.skillID
GROUP BY sm.className,s.skillID";
$r_students = mysqli_query($dbc,$studentInfoQuery);
$num_studentRows = mysqli_num_rows($r_students);
$studentRows = array();
while($row = mysqli_fetch_array($r_students, MYSQLI_ASSOC)) {
// with our query, we only find 1 cell-pair per skill per class
$studentRows[$row['skillName']][$row['className']] = '
<td>' . $row['studentName'] . '</td>
<td>' . $row['studentGrade'] . '</td>';
}
// everybody do their share! // actually, more clean-up
mysqli_free_result($r_students);
for($j = 0; $j < $num_classes; $j++) {
echo "
<tr>
<th>" . $classes[$j] . "</th>";
for($i = 0; $i < $num_skills; $i++) {
// always echo out a cell, even if we have student info for it
// example: if(isset($studentRows['Listening']['1A'])) echo it out else echo cell
if(isset($studentRows[$skills[$i]][$classes[$j]]))
echo $studentRows[$skills[$i]][$classes[$j]];
else
echo "
<td colspan=2>No skill-class-student value</td>";
}
echo "
</tr>";
}
echo '
</tbody>
</table>';
?>
Results:
You are doing fine(although the things can be optimized) up to the last loop of step 4 in your design.
The problem you face right there is that you have a set of results which represent each class in it's rows. Now you need to spread them out in to skill table, importantly, without leaving vertical gaps.
The solution is to do it in a two dimension array in the memory and then create the table from it - because each cell in the memory is easily addressable than cells in an html table.
Memory table is going to be something like this:
|Skill 1 | Skill 2 | Skill3|
|stdnt 1 |stdnt 2,3|stdnt 4|
| | |stdnt 5|
Please note how I have used array_search to get the index of a particular skill and use it in array_push to insert the student in to the correct child array. Then I have just translated it in to an HTML table
I'm replacing your last loop with the following code:
//This is our memory table. Let's create it and add number of child arrays
//equal to number of skills.
$memTable = array();
for ($i = 0; $i <= sizeOf($skills) - 1; $i++) {
$memTable[$i] = array();
}
//Lets spread out your student information in to this 2d array now
foreach ($value as $student) {
//Get the index of the skill
$skillIndex = array_search($student['skillName'], $skills);
//Now go to appropriate child array and insert your student there
array_push($memTable[$skillIndex], $student);
};
//Lets create the table now
$emptyCount = 0;
$currentRow = 0;
//Do until all the skill arrays are empty for a row
while ($emptyCount < 3) {
echo "<tr>";
$emptyCount = 0;
foreach ($memTable as $skillLevel) {
if (sizeof($skillLevel) - 1 < $currentRow) {
$emptyCount ++;
echo "<td>&nbsp</td>";
echo "<td>&nbsp</td>";
}
else {
echo "<td>" . $skillLevel[$currentRow]['studentGrade'] . "</td>";
echo "<td>" . $skillLevel[$currentRow]['studentGrade'] . "</td>";
}
}
$currentRow++;
echo "</tr>";
};
Please note that the skills will be rendered in the table according to the order they are in the $skills array. Please ask me questions if there is any place that is not clear to you. You might need to adjust some String names to adopt in to your code.
UPDATE
while ($emptyCount < sizeof($skills)) is more accurate.

Categories