I'm wanting to have a list of states and the cities under it. I want 5 states per row with the cities that have records under it, then I want it to start a new row. I started trying to figure it out and I've been going for hours and my brain hurts. Can anyone help?
Here's what I have right now:
$lookup = "SELECT state, city, count(city) as num FROM needs WHERE country IS NULL AND
status='posted' GROUP BY state, city ORDER BY state, city";
if ($result = mysql_query($lookup)) {
$num_rows = mysql_num_rows($result);
echo "<table>";
$i = 1;
$cols = 3;
$prev = '';
while ($frows = mysql_fetch_array($result)) {
$fcity = $frows['city'];
$fstate = $frows['state'];
$fcitycount = $frows['num']; // num is holding your count by city
if ($fstate != $prev) {
echo "<tr><td><h2>$fstate</h2></td>";
$prev = $fstate;
}
echo "<tr><td><a href='browseresults.php?city=$fcity&state=$fstate'>$fcity, $fstate ($fcitycount)</a></td></tr>";
}
echo "</table>";
}
EDIT:
It should look like this:
Arkansas Tennessee Missouri
Searcy, AR (1) Bartlett, TN (1) St. Louis, MO (4)
Little Rock, AR (4) Memphis, TN (3) Perry, MO (3)
Benton, AR (2) Branson, MO (1)
Shell, MO (2)
Except it will be done 5 times instead of 3
EDIT 2:
Here's the code I tried but it's still not working :-/
$lookup = "SELECT state, city, count(city) as num FROM needs WHERE country IS NULL AND status='posted' GROUP BY state, city ORDER BY state, city";
if ($result = mysql_query($lookup)) {
$num_rows = mysql_num_rows($result);
echo "<table><td>";
$i = 1;
$j = 1;
$cols = 5;
$prev = '';
while ($frows = mysql_fetch_array($result)) {
$fcity = $frows['city'];
$fstate = $frows['state'];
$fcitycount = $frows['num']; // num is holding your count by city
if ($fstate != $prev) {
echo "<tr><h2>$fstate</h2></tr>";
$prev = $fstate;
}
echo "<tr><a href='browseresults.php?city=$fcity&state=$fstate'>$fcity, $fstate ($fcitycount)</a><br></tr>";
if ($fstate != $prev) {
echo "</td><td>";
}
}
echo "</td></table>";
}
Here is one way to do it, based off your current code attempt. The state and all of its cities are within the same cell.
echo "<table>";
$i = 1;
$cols = 3; // of cells per row
$prev = '';
echo "<tr>"; // start the first row
while ($frows = mysql_fetch_array($result)) {
$fcity = $frows['city'];
$fstate = $frows['state'];
$fcitycount = $frows['num']; // num is holding your count by city
if ($fstate != $prev) {
if($i>$cols){ // check if we have reached our # of $cols
echo "</td></tr><tr>"; // end cell/row and start new row
$i=1; //reset counter
}
elseif ($prev != '') { // if not the first cell/state
echo "</td>"; // end cell before starting new cell/state
}
echo "<td><h2>$fstate</h2>";
$prev = $fstate;
$i++;
}
echo "<a href='browseresults.php?city=$fcity&state=$fstate'>$fcity, $fstate ($fcitycount)</a><br />";
}
echo "</td></tr>"; //end the last cell/row
echo "</table>";
By changing $cols value (ie $cols=5, you can change the number of cells per row.
See an example of this in a phpfiddle - http://phpfiddle.org/main/code/pkg-90i
this creates a table like this-
Related
I'm working on a program to reserve seats for a show. I have a multidimensional array that is created using $row and $column variables. After making a few initial reservations, I need to pass integers into a function/some code to make further reservations.
I've tried looping through the array to find consecutive available seats (value "avail") but it ignores reserved seats or skips over them. I'll need to later use manhattan distance to reserve the best seats (from row 1, seat 6) first.
function to create the array:
//function to create seating chart data structure
function createChart($row, $column){
//create array for row values
$row_chart = array();
for($r=0; $r < $row; $r++){
$row_number = $r + 1;
$row_chart[$row_number] = array(); // array of cells for row $r
}
//create array for column values
$column_chart = array();
for($c=0; $c < $column; $c++){
$column_number = $c + 1;
//$location = $c_num;
$status = "avail";
foreach($row_chart as $key => $value){
$column_chart[$column_number] = $status; //add arrays of "seats" for each row
}
}
//nest the column array into the row array
foreach($row_chart as $key => $value){
foreach($column_chart as $k => $v){
$seating_chart[$key][$k] = $status;
}
}
//$seating_chart = array_combine($row_chart, $column_chart);
return $seating_chart;
}
function to make initial reservations:
$initial_reservation = "R1C4 R1C6 R2C3 R2C7 R3C9 R3C10";
$initial_reservation = explode(" ", $initial_reservation);
echo "<br> <br>";
print_r($initial_reservation);
$initial_res_length = count($initial_reservation);
echo "<br> <br>";
//echo $initial_res_length;
//split each seat up into integers to mark it reserved in the array
//issue for flexibility: find way to break up string by letters and numbers for larger charts
for($a = 0; $a < $initial_res_length; $a++){
$reso_row = substr($initial_reservation[$a], 1, 1);
//echo $reso_row . "<br>";
$reso_column = substr($initial_reservation[$a], 3, 2);
//echo $reso_column . "<br>";
$working_chart[$reso_row][$reso_column] = "reserved";
}
//echo "<br> <br>";
//echo "<pre>" . print_r($working_chart, 1) . "</pre>";
what I have so far in attempt to make further reservations:
//write some code to find consecutive seats
$seats_needed = 4;
$outer_array_length = count($working_chart);
//echo $outer_array_length;
for($d = 1; $d < $outer_array_length + 1; $d++){
for($e = 1; $e < $seats_needed + 1; $e++){
//issue: run through $seats_needed amount of times and executes the code block
//needed: check if $seats_needed amount of seats in available first then run reservation code
if($working_chart[$d][$e] === "avail"){
$working_chart[$d][$e] = "new reservation";
}
else{
echo "Sorry, not possible.";
}
}
break;
}
echo "<br> <br>";
echo "<pre>" . print_r($working_chart, 1) . "</pre>";
I'd like to be able to find a number of available seats ($seats_needed) first, and then loop through to reserve them.
I have initialized the $working_chart with :
$working_chart = createChart(10, 11);
I have written the attempt to make further reservations :
foreach(array_keys($working_chart) as $d ){
$maxColumn = count($working_chart[$d]) - $seats_needed + 1;
for($e = 1; $e <= $maxColumn ; $e++){
if(["avail"] === array_unique(array_slice($working_chart[$d], $e - 1 , $seats_needed))){
$working_chart[$d] = array_replace($working_chart[$d], array_fill($e, $seats_needed, "new reservation"));
break 2;
}
else{
echo "Sorry, not possible.";
}
}
}
I hope it can help you...
Background
I have a script which is used to rotate employees to share an allotment of car parks. Everything works fine i.e. i am able to retrieve a list of employees from a mysql db into an array, sort alphabetically and fill a table in a rotating fasion. All good.
What I am trying to achieve
What I would like to able to do is if I change the month i.e. from August to September the rotation from the current month will continue from where it left over in the previous month. Right now with the current script it will rotate perfectly within the given month but if i enter a new month the rotation is reset.
I have been thinking long and hard as to how i can carry over the rotation but struggling to figure this out.
Personal thoughts..
One thought maybe is should I flag in the mysqldb the last person in the rotation then in the next month continue the rotation beginning from the person who was flagged?
Here is the current working script
<?php
$weeks = array();
$month = 'Aug';
$year = '2015';
$date = new DateTime("first Monday of $month $year");
$thisMonth = $date->format('m');
while ($date->format('m') === $thisMonth) {
array_push($weeks, $date->format('d-m-Y'));
$date->modify('next Monday');
}
//print_r($weeks);
$weeks_count = count($weeks);
//echo $weeks_count;
//=========================================
include_once 'connect.php';
dbconnect("roster");
$NoOfRows = 8;
$NoOfWeeks = $weeks_count;
$totalLots = $NoOfRows * $NoOfWeeks;
$dataArr = array();
//fetch all persons
$query = "SELECT * FROM carpark ORDER BY First_Name";
$result = mysqli_query($conn, $query) or die("error getting data");
while ($row = mysqli_fetch_array($result, MYSQLI_ASSOC)) {
array_push($dataArr, $row['First_Name']);
}
$noOfPersons = count($dataArr);
//Create a new array with filling all lots
while ($noOfPersons < $totalLots) {
$dataArr = array_merge($dataArr, $dataArr);
$noOfPersons = count($dataArr);
}
$weekArr = array_chunk($dataArr , $NoOfRows);
//print the table
echo "<table border=1>";
for ($row = 0; $row < $NoOfRows; $row++) {
if ($row == 0) {
echo "<tr><th></th>";
for ($col = 1; $col <= $NoOfWeeks; $col++) {
$weeks_loop = $col-1;
echo "<th>Week $col<br>$weeks[$weeks_loop]</th>";
}
echo "</tr>";
}
for ($col = 0; $col < $NoOfWeeks; $col++) {
if ($col == 0) {
echo "<tr><td><strong>Bay $row</strong></td>";
}
echo "<td>";
echo $weekArr[$col][$row];
echo "</td>";
}
echo "</tr>";
}
echo "</table>";
?>
Screenshot of output
What should happen is if i change the next month, the rotation should start with Claire, Duncan, Gabriel and so on..
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
}
(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> </td>";
echo "<td> </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.
I try to break my table booking into 3 tables to enable normalization.
Well, I encounter problem when I try to generate 1 bookingID for multiple booking.
I am confuse with looping.
Scenario: customer reserved 2 booths, A01 and A02, (A01 booked from day 1 to day 3, while A02 booked from day 1 to day 2).
System will process the booking, it should generate 2 bookingIDs for A01 and A02, and generate bookingScheduleID for A01_D1, A01_D2, A01_D3 (carry bookingID A01) and A02_D1, A02_D2 (Carry bookingID A02).What should I do to loop and get the following result?
My coding
<?php
include('db.php');
// check array and insert parrentBookingID
// check submitted totalDay
if (isset($_POST['submit']) && isset($_POST['totalDay'])) {
//check day exist or not
$cDay=$_POST['totalDay'];
for ($i=1; $i<=sizeof($cDay); $i++) { //check array size
$temp=0;
foreach ($cDay as $dy) {
$checkDay = $dy;
$checkDay = explode(" ", $checkDay);
echo $checkDay[0]; // boothAlias
echo $checkDay[1]; // boothID
echo $checkDay[2]; // day
$checkDayResult = mysql_query(
"SELECT * FROM bookingDetail WHERE boothID='$checkDay[1]'
and day='$checkDay[2]' and username='$user'"
);
$num_rows_check = mysql_num_rows($checkDayResult);
if ($num_rows_check) {
echo "Exist";
$temp += 1;
} else {
$temp += 0;
}
}
} //FOR LOOP CHECK ARRAY SIZE
echo "temp".$temp;
if ($temp != 0) {
echo "Please try again";
} else {
// insert parentBookingID
$parent = mysql_query(
"INSERT into booking (custNo,eventID,dateBook)
VALUES ('$userID','$event',NOW())"
);
$parentBookID = mysql_insert_id();
// End check array and insert parrentBookingID
// check booth, create bookingDetailID
$booth = $_POST['totalDay'];
//for loop check array size for check repeat booth.
for ($j=1; $j <= sizeof($booth); $j++) {
$current = explode (" ", $booth);
} // end for loop check repeat loop.
// end check booth.
$totalDay = $_POST['totalDay'];
$allBooth = "";
foreach ($totalDay as $d) {
echo $d;
$bookingInfo = $d;
$bookingInfo = explode(" ", $bookingInfo);
echo $bookingInfo[0]; // boothAlias
echo $bookingInfo[1]; // boothID
echo $bookingInfo[2]; // day
$result = mysql_query(
"SELECT * FROM bookingDetail WHERE
boothID='$bookingInfo[1]' and day='$bookingInfo[2]'
and username='$user'"
);
$num_rows = mysql_num_rows($result);
if ($num_rows) {
echo "Exist";
} else {
$str = "INSERT INTO bookingDetail
(username, custNo, eventID, date, day,
boothAlias, boothID, parentBookID) VALUES ('$user',
'$userID','$event',NOW(),'$bookingInfo[2]',
'$bookingInfo[0]','$bookingInfo[1]','$parentBookID');";
$res = mysql_query($str);
if ($res) {
echo 'Success';
} else {
echo 'Failure';
}
$allBooth = substr($allBooth, 0, -2);
echo "<p>Booth(s): <strong>$allBooth</strong>
<strong>$user</strong> <strong>$event</strong>
<strong>$userID</strong></p>\r\n";
}
}
} // close check $temp
header("refresh:5;url=mybooking.php");
echo "<img src='loading16.gif' style='margin-top:8px; float:left'/>";
echo 'You\'ll be redirected in about 5 secs. If not, click
here.';
} else {
echo "You do not make any booking";
header("refresh:5;url=booking2.php");
echo "<img src='loading16.gif' style='margin-top:8px; float:left'/>";
echo 'You\'ll be redirected in about 5 secs. If not, click
here.';
}