I am attempting to make a timetable using data in a MySQL table that has the day, start and durtaion of each event.
My logic at the moment goes like this.
Find all events with monday, put in an array for monday
Find all events with tuesday, put in an array for tuesday
etc
then i run a for each loop on each array to go through each time slot in the day (9-5) and if it matches the current event, create a table cell, if not create and empty cell and finally if the event duration is longer than 1 slott then dont put anything. here is my code for the above:
function createTableEvent($day,$previousfinish)
{
$completeDay = '';
$day = explode(',',$day);
$ev = $day[0];
$start = $day[1];
$end = $day[2];
$event = "<div class=\"table_event\">$ev<br>Starts:$start<br>Ends:$end<br></div>";
$times= array('09','10','11','12','13','14','15','16','17');
//TIMES
foreach ($times as $time)
{
if($start == $time.":00" && $previousfinish == !)
{
$completeDay .= "<td class=\"$time\" colspan=\"$end\">
<div class=\"table_event\">$event</div></td>";
$previousfinish = $end;
}
else if($previousfinish > 1
{
}
else
{
$completeDay .= "<td class=\"$time\" colspan=\"1\"></td>";
}
}
return $completeDay;
}
The reason i wanna skip the cell if it is more than 1 is because if an event runs over more than one block, i set the column span to the duration of the event, there for it shhouldnt put a cell in for the next time if the previous event was longer than one block.
My output works for single hour events however not when a day has say 1 2 hour event and a 2nd 1 hour event. My code still makes the extra cells for the times that should be empty.
Any input or help would be very useful
The obvious things I notices were:
The second if statement (right after the 'else')'s condition is not
followed by a closing ')'.
I couldn't make out if this is wanted, but there are no commands to
whenever this condition is met
At the first condition inside the for loop you compare the
$previousfinish parameter to '!'. Is this really what you want to do?
Did you mean to compare it to '1'?
Other things I noticed is that if the last condition is met, you put the event time but not the event name (as you did in the first place).
I tried to further investigatethe problem, but it's bit hard, since I don't know what data is passed to the function in the arguments.
I suggest you fix the above problems and see if this fixes you problem.
If not, I would be happy to look further into this issue, if you supply a sample data being passed to the function.
Also, I re-arranged the code for readability, if you find it better -
<?php
function createTableEvent($day, $previousfinish)
{
$completeDay = '';
list ($ev, $start, $end) = explode(',',$day);
$event = "<div class=\"table_event\">$ev<br>Starts:$start<br>Ends:$end<br></div>";
//TIMES
foreach (array('09','10','11','12','13','14','15','16','17') as $time)
{
if ($start == ($time.":00") && $previousfinish == !)
{
$completeDay .= "<td class=\"$time\" colspan=\"$end\">
<div class=\"table_event\">$event</div></td>";
$previousfinish = $end;
}
else if($previousfinish > 1)
{
}
else
{
$completeDay .= "<td class=\"$time\" colspan=\"1\"></td>";
}
}
return $completeDay;
}
?>
Related
its been a while (5 years) since my last time here making questions.
I need help, I'm developing an event calendar and I'm stuck in this.
I want to have event header and event body, so far so good, but I just want one header if there are more than one event in each day.
So today I've a dinner at 21h, my event should have Friday , November 23 and Dinner at 21h.
Perfect, I can do this, but what about if I do have a meeting before dinner, at 19h?
I want just one time the same header ... Friday, November 23 but 2 bodies...
thanks!
my piece of code
foreach($eventos[$data_do_dia] as $evento) {
$i = count($eventos[$data_do_dia]);
if($i == 1) {
$agenda .= " dia ".date("d-m-Y",strtotime($evento['dia']))."</b>";
add the event
} else {
repeat the same but just one time
$agenda .= " dia ".date("d-m-Y",strtotime($evento['dia']))."</b>";
add event one
add event two
...
}
}
I've changed the loop so that there isn't any repeated code, this basically means that if there is only one event, it converts into an array, assuming that isset($evento[0]) will pick up there aren't sub-arrays, it wraps the one entry into a new array.
It then loops over the array and creates the string with the date/time/details. You will probably want to change the format, but the principle is the same...
$agenda = "";
foreach($eventos as $evento) {
if ( !isset($evento[0]) ) {
$evento = [$evento];
}
$agenda .= " dia ".date("d-m-Y",strtotime($evento[0]['dia'])).PHP_EOL;
foreach ( $evento as $time ) {
$agenda .= " time ".$time['hora']." ".
$time['titulo']." ".$time['evento'].PHP_EOL;
}
}
echo $agenda;
I've been putting together a simple linear weekly event calendar script, which calls entries from a MYSQL database. It displays a sort of "8 day week" (Sunday to Sunday inclusive)
My MYSQL query is like so:
$results = $dbh->query('SELECT * FROM calendar WHERE YEARWEEK(event_date) = YEARWEEK(NOW()) OR (WEEKDAY(event_date) = 6 AND YEARWEEK(event_date) = YEARWEEK(NOW()) + 1) ORDER BY event_date ASC');
When a given day has multiple event entries, I keep the day/date heading from repeating:
$currentday = '';
$showday = true;
foreach($results as $row) {
$weekday = date("l", strtotime($row['event_date'])); {
if ($currentday != $row['event_date']) {
$showday = true;
$currentday = $row['event_date'];
}
if ($showday) {
$weekday = date("l", strtotime($row['event_date']));
if($weekday == "Sunday") {
echo "<h3 class='sunday'>";
echo $weekday;
}
else {
echo "<h3>";
echo $weekday;
}
echo date("F j", strtotime($row['event_date']));
$showday = false;
}
}
... followed by the remaining details.
All that works great.
What I'm trying to accomplish now is to group each day's results visually by means of an HTML hook.
To accomplish that, I'm trying to group each day's events within a div with a class of "daybox". I can create/open the div with this, just after the first if clause:
if ($showday) { ?><div class="daybox">
That successfully opens/create a new div for each distinct day of the foreach loop.
The problem is closing it. I tried a corresponding if $showday closing code at the end of my foreach, but in retrospect, that wasn't what I was looking for, and obviously it didn't work.
What I think I need is a way to determine whether I've reached the last entry for a given day (i.e. event_date in my database), and base my if clause off that. But so far I'm stumped how I need to articulate that.
Am I on the right track, and how would I formulate my final if clause?
Thanks!
Well, this isn't a real PHP solution, but I found a workaround that I can live with.
I changed this line:
if ($showday) { ?><div class="daybox">
to this:
if ($showday) { echo "</div><div class='daybox'>"; }
That gives me an anomalous closing div tag before the first day of the calendar, but I reconciled my HTML by placing an opening div tag outside of my foreach loop. (In my case, I already had an h2 for a "This Week" title, so now I've got the heading wrapped in a div.)
This works for this particular use case, but if somebody has the proper PHP answer, please feel free to provide.
My friend Anthony, who is a hardcore programmer, although not really a PHP guy, provided the actual code to accomplish this properly.
Below the $weekday = date ... line, the code above has been replaced with this:
if ($currentDay != $weekday) {
if ($currentDay != '') {
echo "</div>";
}
$currentDay = $weekday;
$showday = true;
echo "<div class='daybox'>";
}
?>
<section class="calendar-item">
<?php
if ($showday) {
if ($weekday == "Sunday") {
echo "<h3 class='sunday'>";
} else {
echo "<h3>";
}
echo $weekday;?>
</h3><p class="date-detail"><?php
echo date("F j", strtotime($row['event_date'])); ?></p><?php
$showday = false;
}
Works a treat. Now I need to study it in order to fully grasp how he did it.
I'm having two comboboxes. One is like 'admin', 'city' , 'theatre' and the other one is daily and weekly. If user select one of item in first and daily in second it shows daily operations. If user select one of item in the first one select nothing in second one it shows daily and weekly operations. If user does not select anything in first and daily in second it brings all operations daily and son on.
Therefore I think there is 2^3 if conditions. Is there anyway to reduce this? I am using PHP language but I think core algorithm is same in all languages!
Following is what I have done so far for three conditions if it is admin and daily and weekly:
<?php
if(strlen($_POST['attribute'])>0)
{
echo "For admin: ";
echo "</br>";
//If admin
if($_POST['attribute'] == 'Admin'){
//If daily
if($_POST['date'] == 'Daily'){
echo "The only feature to show update is making a user admin\n";
echo "</br>";
$fh = fopen('back-up/makeadmin.txt','r');
$foo = true;
while ($line = fgets($fh)) {
if($foo){
//Current time
$now = new DateTimeImmutable();
//One week ago
$oneDayAgo = $now->sub(new DateInterval('P1D'));
echo "</br>";
echo "</br>";
$date = DateTime::createFromFormat('m/d/Y h:i:s a+', $line);
//Here you can compare your dates like any other variables
if ($date > $oneDayAgo) {
/* Nothing echo "Current date is less than 1 week old";
Break;
*/
break;
}
if ($date < $oneDayAgo) {
echo "$line";
}
var_dump($line);
}
$foo = (!$foo);
}
fclose($fh);
}
else { /*if($_POST['date'] == 'Weekly'){*/
echo "The only feature to show update is making a user admin\n";
echo "</br>";
$fh = fopen('back-up/makeadmin.txt','r');
$foo = true;
while ($line = fgets($fh)) {
if($foo){
//Current time
$now = new DateTimeImmutable();
//One week ago
$oneWeekAgo = $now->sub(new DateInterval('P1W'));
echo "</br>";
echo "</br>";
$date = DateTime::createFromFormat('m/d/Y h:i:s a+', $line);
//Here you can compare your dates like any other variables
if ($date > $oneWeekAgo) {
/* Nothing echo "Current date is less than 1 week old";
Break;
*/
}
if ($date < $oneWeekAgo) {
echo "Current date is more than 1 week old";
}
var_dump($line);
}
$foo = (!$foo);
}
fclose($fh);
}
//If not daily
else
{
echo "weekly";
}
}
}
else
{
echo "Not admin";
}
?>
I'm not familiar with PHP, but if your code has a lot of hard-coded if statements, it's a clear sign that you need a better data structure, or maybe any data structure at all.
For example, you duplicate a whole block of code that only differs in that the first uses $oneDayAgo and the second $oneWeekAgo?. You could easily make that into a variable someTimeAgo that is a time span of seven days or one day, depending on the value of your second list box.
I'm not sure what the selection of the first box is for, maybe the file to read from? You might be able to find some common behaviour fro these three cases, too, and try to express them in variables rather than code.
You could probably store the relevant data is an associative array whose keys are the values of the list boxes:
$span = array("Daily" => "P1D", "Weekly" => "P1W");
As a next step, you could even populate your list from PHP with the keys (the values left of the fat arrows) of the array and you could easily extens the list together with the time spans without adding any new code, just new data.
Lastly, an UI niggle: If you have only two values, you shouldn't use a drop-down list box. Use a group of two radio-buttons next to each other and the user will be able to see both options at one glance without having to click anything. (I also don't think these are combo boxes, because combo boxes allow to enter a value by either typing it in manually or selecting it from a drop-down list.)
So I've got a bunch of 'events' in a table in which they have a start and an end column (both DATETIME). I'm fetching every event for a single day and somehow need to group them together so that they can be displayed as a single HTML block.
For example...
Row #1: Has a duration of 30 minutes, starts at 09:00:00 and ends at 09:30:00
Row #2: Has a duration of 30 minutes, starts at 09:30:00 and ends at 10:00:00
Row #3: Has a duration of 90 minutes, starts at 12:00:00 and ends at 13:30:00
What would be the best way to know that I need 2 html blocks... One that is a div that has a 60px height (for rows 1 and 2), and then because there's a break between 10:00:00 and 12:00:00 to have the another div that is 90px height (row 3).
Can this be done with MySQL somehow? Or do I have to do a PHP loop to check for empty spaces of time in order to know when I should close a div and begin a new one?
Any help would be beneficial.
This is more of a logic question than code question.
You can do this in MySQL. One way is using a correlated subquery to determine when "event periods" begin. A new event period begins when it does not overlap with any others. Then use this information to assign an "event period id" to each event.
Such a query would perform reasonably well with the right indexes.
You could do this in php. I am biased toward putting such logic into the database rather than in application code.
My personal bias is to keep formatting out of the database layer. I would do this using PHP.
Assumptions based on the text of your question:
Duration is stored in the database
Duration increment = 30 minutes
Events do not overlap.
Duration data has been queried with ODBC
Duration query includes ORDER BY Start_Time
Duration data loaded into appropriate $result variables
Event blocks are 30px per event.
$job_count = 0;
$event_increment = 30;
$event_height = 30;
$this_block_height = 0;
$this_block_content = "";
while(odbc_fetch_row($result)) {
//fetch all your results into arrays
$duration[] = odbc_result($result, 1);
$start_time[] = odbc_result($result, 2);
$end_time[] = odbc_result($result,3);
$event_count++;
}
for($x=0;$x < $event_count; $x++) {
//loop through the arrays to format the blocks
if($x + 1 == $job_count) {
//if this is true, we are at the last element
$this_block_height += $event_height;
$this_block_content .= $start_time[$x] . " to " . $end_time[$x] . PHP_EOL;
echo "<DIV style='height:" . $this_block_height . "px;'>$this_block_content</DIV>";
}
else {
if($end_time[$x] == $start_time[$x+1]) {
//if this is true there is no gap.
$this_block_height += $event_height;
$this_block_content .= $start_time[$x] . " to " . $end_time[$x] . PHP_EOL;
}
else {
//gap identified
//write old block to file with padding on the end
//reset values to start over
$end_seconds = strtotime($end_time[$x]);
$start_seconds = strtotime($start_time[$x+1]);
$gap = $start_seconds - $end_seconds;
$gap_minutes = $gap / 3600;
$gap_increments = $gap_minutes / $event_increment;
$this_block_height += ($event_height * $gap_increments);
echo "<DIV style='height:" . $this_block_height . "px;'>$this_block_content</DIV>";
//this will put the space padding at the end of the first block
//instead of at the start of the second block
$this_block_height = 0;
$this_block_content = "";
}
}
}
Sorry if this has been asked before however I am having trouble finding the answer to my problem.
I am trying to build a calendar system and schedule system for my web application in PHP and having difficulty with one particular area.
I have a "for" statement where it will draw up the times of the day starting at 12:00AM and finishing at 11:30PM
Inside this for loop, I have a foreach which i want to echo out the objects in an array that match a particular time.
Everything I have tried which includes using for,while and foreach statements don't show what I am after which is the events lining up next to the time.
here is my code
<?php
$tStart = strtotime($start_time);
$tEnd = strtotime($end_time);
$tNow = $tStart;
while($items = mysql_fetch_object($result)){
$events[] = $items;
}
for($tNow=$tStart; $tNow<$tEnd; $tNow=strtotime('+30 minutes',$tNow)){
// Time to color the rows to make it easier to read
if(!isset($day_row)){
$day_row = "0";
}
if(isset($day_row) && $day_row >= "2"){
$day_row--;
}
else{ $day_row++;
}
//This bit draws the first column.
echo "<tr><td class=\"day_row".$day_row."\" width=\"70px\">".date("h:i A",$tNow)."</td>";
// MySQL stuff is now here
foreach($events as $e => $item){
if($item->apnt_start == $tnow){
$rowspan = ((strtotime($item->apnt_finish)-strtotime($item->apnt_start))/"1800");
echo "<td class=\"day_row_apnt\" rowspan=\"$rowspan\">".$item->apnt_start."-".$item->apnt_finish." ".$item->apnt_brief."</td></tr>";
}
}
}
?>
at present i am given a page with
12:00 AM
12:30 AM
01:00 AM
01:30 AM
02:00 AM
02:30 AM
03:00 AM
03:30 AM
04:00 AM
04:30 AM
05:00 AM
05:30 AM
Next to the time I want the appointment with matching time.
I am trying to achieve something similar to http://mrbs.sourceforge.net/
I can't use their system however as I can't integrate it properly and I have tried looking at their code and it seems to be pointing at many files and i am having trouble trying to understand the function i am after.
Please let me know if this is not clear enough and will try to explain further.
You need to define and set value for variables below:
$start_time = "09:00 AM";
$end_time = "11:30 PM";
Also you need to add query and database connection (above while($items = mysql_fetch_object($result)){ statement):
mysql_connect("hostname", "user", "password");
mysql_select_db("mydb");
$result = mysql_query("select * from mytable");
EDIT:
You should use while mysql_fetch_assoc instead of mysql_fetch_object.
Replace
while($items = mysql_fetch_object($result)){
with
while($items = mysql_fetch_assoc($result)){
Delete: $events[] = $items;
Ensure your while statement above ends after all code is executed (code you listed in your question) - closing bracket }.
Okay, this should work for you.
<?php
$tStart = strtotime($start_time);
$tEnd = strtotime($end_time);
$tNow = $tStart;
echo '<table>';
while($events = mysql_fetch_assoc($result)){
for($tNow=$tStart; $tNow<$tEnd; $tNow=strtotime('+30 minutes',$tNow)){
// Time to color the rows to make it easier to read
if(!isset($day_row)){
$day_row = "0";
}
if(isset($day_row) && $day_row >= "2"){
$day_row--;
}
else{ $day_row++;
}
//This bit draws the first column.
echo "<tr><td class=\"day_row".$day_row."\" width=\"70px\">".date("h:i A",$tNow)."</td>";
if(strtotime($events['apnt_start']) == $tNow) {
$rowspan = ((strtotime($events->apnt_finish)-strtotime($events->apnt_start))/"1800");
echo "<td class=\"day_row_apnt\" rowspan=\"$rowspan\">".$events->apnt_start."-".$events->apnt_finish." ".$events->apnt_brief."</td></tr>";
}
} //end for
} //end while
echo '</table>';
?>
I would like to thank everyone that provided advice on this issue, I have finally got it working with added another variable and using a method of storing an array in an array.
The final code looks like
<?php
$tStart = strtotime($start_time);
$tEnd = strtotime($end_time);
$tNow = $tStart;
$events = array();
$eas = "0"; // eas stands for Event Array Start. this will be used to cycle through the events in the array.
while($items = mysql_fetch_assoc($result)){
$events[] = $items;
}
for($tNow=$tStart; $tNow<$tEnd; $tNow=strtotime('+30 minutes',$tNow)){
// Time to color the rows to make it easier to read
if(!isset($day_row)){
$day_row = "0";
}
if(isset($day_row) && $day_row >= "2"){
$day_row--;
}
else{ $day_row++;
}
//This bit draws the first column.
echo "<tr><td class=\"day_row".$day_row."\" width=\"70px\">".date("h:i A",$tNow)."</td>";
if(strtotime($events[$eas]['apnt_start']) == $tNow) {
$rowspan = ((strtotime($events[$eas]['apnt_finish'])-strtotime($events[$eas]['apnt_start']))/"1800");
echo "<td class=\"day_row_apnt\" rowspan=\"$rowspan\" >".$events[$eas]['apnt_start']."-".$events[$eas]['apnt_finish']." ".$events[$eas]['apnt_brief']."</td></tr>";
$eas++;
}
else{
echo "<td class=\"day_row".$day_row."\"></td>";
}
} //end for
?>
By using the variable $eas I was able to then control which number it would start at by setting it to 0 initially and then when it found an entry with a matching time it went through the if statement where at the end of the if statement it was given $eas++ to increment.
This then proved that if there was no appointment the $eas would not run and it would not increment thus remaining on the last incremented $eas.
Thanks again for everyone's help.