How to manage couple of combo box working together? - php

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.)

Related

PHP: detect end of duplicate column results (calendar day)

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.

Is there anyway way to logically compare PHP DateTime objects?

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));

taking the latest content from a dynamic array

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]";
}
?>

Having trouble with creating a timetable

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;
}
?>

Adding rows to an array in PHP

I have loaded an associative array of records from a MySQL database table.
The array consists of 1 to 7 rows representing one week of entries,
which might not have been entered for each day.
How can I insert blank rows into the array for the missing days
so that I can easily display the data in a table?
I don't need to update the database with the blanks.
Example:
Field1 Field2 Field3 Field4 .... Field#
Record[0]
Record[1]
Record[2]
Record[3]
Record[4]
Record[5]
Record[6]
Field4 is the date as yyyy-mm-dd
I load the array automatically using a start date and end date
Some weeks there will be a Sun, Tue, and Fri or Mon, Tue, Wed, Fri & Sat.
this is simple:
Do you know how many "Fields" you have for each day? let's say it's "num of fields"
$records = array_fill(0, 7, array_fill(0, <num of fields>, ''));
what this does is it creates a blank array from [0] to [6] and for each array element it inserts another array of "Fields", with "num of fields", each of which is set to an empty string ''.
Now that you have this, you read your data from the mysql table and if you selectively assign $records by index (i'm assuming), the rest of them will stay blank.
Keep in mind that you can reassign an element of $records array by using something like
$records[5] = array('New value', 'Field2 value');
which is what you do when you read data from mysql table.
Do you use some kind of index in your mysql table to correspond to the numbered day in a week?
comment here if you get stuck with mysql part.
If your array is associative, then when constructing the table why not just check for and skip the empty rows? As an example:
Example 1:
if ($row['Monday'] == '')
{
// draw blank template
}
else
{
// draw using live data
}
Based on added example (untested; for php 5.1 and above):
Example 2:
for($i = 0; $i < count($Record); $i++)
{
$recordDate = strtotime($Record[$i][field4]);
$dayOfWeek = $date('N', $recordDate);
switch ($dayOfWeek)
{
case '1':
// Monday
break;
case '2':
// Tuesday
break;
// and so on...
}
}
Edit
The above code assumed that your rows are in weekday order, with possible omissions. The problem with the first example, is that the array is not associative quite like the example. The problem with the second example, is that a missing weekday row results in a completely skipped output, which could provide a table like MTWFS (skipped Thursday).
So, you need to build a loop that draws each day of the week, and checks all of the rows for the appropriate day to draw. If the day is not found, an empty day is drawn:
Example 3:
$dayNames = {'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'};
// Loop that walks the days of the week:
for($d = 1; $d < 7; $d++)
{
// Loop that checks each record for the matching day of week:
$dayFound = false;
for($i = 0; $i < count($Record); $i++)
{
$recordDate = strtotime($Record[$i][field4]);
$dayOfWeek = $date('N', $recordDate);
// output this day name in your own formatting, table, etc.
echo $dayNames[$i];
if ($dayOfWeek == $d)
{
// output this day's data
$dayFound = true;
break;
}
if (!$dayFound)
{
// output a blank template
}
}
}
Edit 2
Ok it seems you are more interested in having a fully populated array of weekdays than an output routine (I was assuming you would just want to draw the tables in php or something). So this is my example of how to arrive at a 7-day array with no gaps:
Example 4:
$weekData = array(); // create a new array to hold the final result
// Loop that walks the days of the week, note 0-based index
for($d = 0; $d < 6; $d++)
{
// Loop that checks each record for the matching day of week:
$dayFound = false;
for($i = 0; $i < count($Record); $i++)
{
$recordDate = strtotime($Record[$i][field4]);
$dayOfWeek = $date('N', $recordDate);
// Add one to $d because $date('N',...) is a 1-based index, Mon - Sun
if ($dayOfWeek == $d + 1)
{
// Assign whatever fields you need to the new array at this index
$weekData[$d][field1] = $Record[$i][field1];
$weekData[$d][field2] = $Record[$i][field2];
$weekData[$d][field3] = $Record[$i][field3];
$weekData[$d][field4] = $Record[$i][field4];
// ...
break;
}
if (!$dayFound)
{
// Assign whatever default values you need to the new array at this index
$weekData[$d][field1] = "Field 1 Default";
// ...
}
}
}
Without having seen your current code (as requested in the comments by Felix Kling), my guess is that you will need to loop through your array, passing it to a function (or passing the array to the function) which checks Field4 and keeps track of which days of that week have data and fills in those missing days. This would be easier if the array was in order to start with (as you would only need to track the previous 'entry' rather than the entire week).
I'm a bit busy currently, here's some pseduo-code that will need to be expanded etc.
$formattedWeek = getFormattedWeek($inputArray);
function getFormattedWeek($input) {
$nextDay = 'Sunday';
foreach ($input as $entry) {
if (date-call-that-returns-day-of-the-week !== $nextDay) {
$output[] = 'add whatever you need to your array';
} else {
$output[] = $entry;
}
$nextDay = call-to-increase-the-day-or-loop-back-to-Sunday();
}
return $output;
}
You should get the picture.

Categories