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.
Related
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.
This is part of a simple project that logs payroll hours as a datetime object in MySQL 5.5. I am trying to compare two datetime values to see if they are at least 30 minutes apart. Sounds simple enough but the value of $lastshiftend keeps being set to the same value as $mealendtime and I don't see where or how. That seems to be the only problem but there definitely could be other things I am missing. TIA.
if ($result = mysqli_query($conn, $select)) {
$row_count = mysqli_num_rows($result);
if($row_count == 1) {
// 30 Minute Meal Break
$lastshiftend = new DateTime($row[3]);
$mealendtime = new DateTime('NOW');
$mealtime = $mealendtime->diff($lastshiftend);
$mealminend = $lastshiftend->add(new DateInterval(PT30M));
// $mealminend = $lastshiftend->modify('+ 30 minute');
if($mealendtime < $mealminend) {
echo '<br>Colorado State law requires meal breaks to be at least 30 minutes in length.';
echo '<hr>Main Menu';
} else {
echo 'Log it!';
// header("Location: ./ActionClockIn.php");
}
} else {
echo 'Error! If you ended up here something broke!.';
echo '<hr>Main Menu';
}
}
Unless you use DateTimeImmutable() your DateTime objects will be modified when you call methods like DateTime::add() or DateTime::modify()
$lastshiftend = new DateTimeImmutable($row[3]);
// Now $lastshiftend is unchanged
$mealminend = $lastshiftend->add(new DateInterval(PT30M));
It looks like you will need that for both DateTime objects
$lastshiftend = new DateTimeImmutable($row[3]);
$mealendtime = new DateTimeImmutable(); //"NOW" is not necessary
$mealtime = $mealendtime->diff($lastshiftend);
$mealminend = $lastshiftend->add(new DateInterval(PT30M));
A small background of myself is that I'm fairly new to php. I work as an IT assistant and have been asked to edit one of the pages our designers use for samples. I cannot point you to the page as it is an internally hosted page.
I'm honestly not even sure if the question is asked correctly but please bear with me.
The page has a 'request completion date' field within a table that outputs 6 dates in a list, the designers only want it to output the latest date from that list instead of all 6, usually these will be empty so it's no use having them printed.
The code to put them is as follows;
if ($database_data['request_confirmed_comp_date'] > "0")
{ $request_confirmed_completion_date = date("d/m/Y", $database_data['request_confirmed_comp_date']); }
else
{ $request_confirmed_completion_date = " -"; }
if $database_data['request_confirmed_comp_date2'] > "0")
{
$request_confirmed_completion_date2 = date("d/m/Y", $database_data['request_confirmed_comp_date2']);
}
else
{
$request_confirmed_completion_date2 = " -";
}
if ($database_data['request_confirmed_comp_date3'] > "0")
{
$request_confirmed_completion_date3 = date("d/m/Y", $database_data['request_confirmed_comp_date3']);
}
else
{
$request_confirmed_completion_date3 = " -";
}
if ($database_data['request_confirmed_comp_date4'] > "0")
{
$request_confirmed_completion_date4 = date("d/m/Y", $database_data['request_confirmed_comp_date4']);
}
else
{
$request_confirmed_completion_date4 = " -";
}
if ($database_data['request_confirmed_comp_date5'] > "0")
{
$request_confirmed_completion_date5 = date("d/m/Y", $database_data['request_confirmed_comp_date5']);
}
else
{
$request_confirmed_completion_date5 = " -";
}
if ($database_data['request_confirmed_comp_date6'] > "0")
{
$request_confirmed_completion_date6 = date("d/m/Y", $database_data['request_confirmed_comp_date6']);
}
else
{
$request_confirmed_completion_date6 = " -";
}
if ($database_data['request_date_required'] > "0")
{
$request_date_required = date("d/m/Y", $database_data['request_date_required']);
}
else
{
$request_date_required = "-";
}
if ($database_data['request_date'] > "0")
{
$request_date = date("d/m/Y", $database_data['request_date']);
}
else
{
$request_date = "-";
}
It is then called into play using;
echo '<td><b>1.</b>'.$request_confirmed_completion_date.'<br /><b>2.</b>'.$request_confirmed_completion_date2.'<br /><b>3.</b>'.$request_confirmed_completion_date3.'<br /><b>4.</b>'.$request_confirmed_completion_date4.'<br /><b>5.</b>'.$request_confirmed_completion_date5.'<br /><b>6.</b>'.$request_confirmed_completion_date6.'</td>';
Now I may not have much php knowledge, but I know that's a horribly long way of doing that. Is there anyway that I could pull the latest date out of an array, created by the the first block of code, and then output them into the table.
Thanks for any help or advice, even if you could just point me in the right direction as to what loop to use would be helpful.
Edit: I've uploaded the full file online here, hopefully that will clear up some confusion.
You want to use the php function asort. Since all of your values look to be numeric, you should be able to do a standard sort and pull off the last item with array_pop.
It might look something like this:
asort($database_data);
$latest = array_pop($database_data);
echo date('m/d/Y', $latest);
Create an array with the variable names, like if the variables are $A, $B and $C, then
$vars = array("A","B","C");
foreach($vars as $var_name){
if($database_data[$var_name] > "0")
$$var_name = $database_data[$var_name];
else
$$var_name = "-";
}
Note: A, B and C are dummy variable names, as the variable names are too long in your code :-)
Firstly there is a problem with your if conditions, you can't say $x > "0" because with using double-quotes you are using 0 as a string. You should use integer $x > 0.
Now here my answer :
I couldn't understand your system very well, so i'm assuming always there will be 6 dates.
for($q = 0;$q < 6; $q++)
{
if($database_data[...][$q] > 0)
$dates[] = date("d/m/Y", $database_data['...'][$q]);
else
$dates[] = " - ";
}
As you see, you have to fetch your database datas as an array $database_data['...'][].
If you can tweak the original SQL statement, which probably looks something like this:
select request_confirmed_comp_date, request_confirmed_comp_date2, request_confirmed_comp_date3, request_confirmed_comp_date4, request_confirmed_comp_date5, request_confirmed_comp_date6
from sometablename
where somefield='something'
You can tweak it to use shorter (and consistent) field names
select request_confirmed_comp_date as date1, request_confirmed_comp_date2 as date2, request_confirmed_comp_date3 as date3, request_confirmed_comp_date4 as date4, request_confirmed_comp_date5 as date5, request_confirmed_comp_date6 as date6
from sometablename
where somefield='something'
And then in PHP use an array to iterate over the field names like so:
<?php
$lastCompletionDate=""; //start by assuming there was no completion date
for($i=1;$i<=6;$i++) { //check to see if any field is after the last known completion date
if ($database_data['date'.$i] && (date("d/m/Y", $database_data['date'.$i]) > $lastCompletionDate)) {
//if so, store the new date
$lastCompletionDate=date("d/m/Y", $database_data['date'.$i]);
}
}
if($lastCompletionDate) {
echo "The last completion date was $lastCompletionDate\n";
}else {
echo "There was no completion date.\n";
}
?>
An alternative solution would be to use the SQL engine's own internal functions to find the highest date like so:
select greatest(request_confirmed_comp_date,
request_confirmed_comp_date2,
request_confirmed_comp_date3,
request_confirmed_comp_date4,
request_confirmed_comp_date5,
request_confirmed_comp_date6) as greatestcompdate
from sometablename etc...
and then refer to that in PHP like
<?php
if($database_data['greatestcompdate']) {
echo "There was a greatest completion date and it was $database_data[greatestcompdate]";
}
?>
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;
}
?>
<?php
// initial value
$week = 50;
$year = 2001;
$store = array();
do
{
$week++;
$result = "$week/$year";
array_push($store,$result);
if($week == 53){
$week = 0;
$year++;//increment year by 1
}
continue;
}
// End of Loop
while ($result !== "2/2002");
?>
print_r($store);
result want return will be
array("51/2001", "52/2001", "01/2002", "02/2002");
What is my problems by using while using do..while ,continue?
Your arguments to array_push are the wrong way around. Read the manual entry for functions you use. Turn on warnings on your server; running this in codepad showed me the problem immediately. [Edit: You have now quietly fixed that in your question.]
You also have a typo: $i instead of $week.
Finally, you test against "02/2002", but for that month the string will be "2/2002".
Fixed code (live demo):
<?php
// initial value
$week = 50;
$year = 2001;
$store = array();
do
{
$week++;
$result = "$week/$year";
array_push($store, $result);
if($week == 53){
$week = 0;
$year++;//increment year by 1
}
continue;
}
// End of Loop
while ($result !== "2/2002");
?>
In general, I'd recommend against loops like this. As you've discovered, your code is very fragile because you're testing for just one very specific value, and if that value is not precisely correct you get an infinite loop.
Instead, consider comparing $week and $year separately and numerically:
while ($week < 2 && $year <= 2002)
Next time please include in your question the output that you are seeing, as well as the output that you want to see. It'll save us time in reproducing your problem.
I may not be understanding this correctly... If you could explain a bit more that'd help.
Try turning the loop into a function, and turn the while(..) to check the functions variable.
then just call it 4 times to fill your array.