For the life of me I cannot find anywhere on the internet that has any documentation on how to solve my problem. I've seen a massive amount of ways to calculate differences in time but I can not seem to put something together that works for my situation.
I'm currently building a time management/ticket system that is a plugin for WordPress. I am using custom tables and not the WordPress tables. I have a table that contains all the main ticket information and another table that contains all the start/stop times. Once the user marks the ticket as complete it will then take all the start/stop time values and calculate the total time spent and then place that total time value into a "total_time" column in the main ticket table.
I'm querying the database and pulling the start/stop times by using:
$start_times = $wpdb->get_results($start_times_query);
$stop_times = $wpdb->get_results($stop_times_query);
Now I have the information in 2 array's. Is this the way I should be doing this?
The array's give me this (for start times):
Array ( [0] => Array ( [time] => 2016-04-29 12:02:43 ) [1] => Array ( [time] => 2016-04-29 12:04:18 ) [2] => Array ( [time] => 2016-04-29 12:06:07 ) [3] => Array ( [time] => 2016-04-29 12:07:56 ) [4] => Array ( [time] => 2016-04-29 12:10:30 ) [5] => Array ( [time] => 2016-04-29 12:11:59 ) )
(Same format for the end times)
Then I break down the array using:
$startTimes = array_column($startTimes, 'time');
$endTimes = array_column($endTimes, 'time');
Which now gives me this as the array (this one is just the start times, but same format for the end times):
Array ( [0] => 2016-04-29 12:02:43 [1] => 2016-04-29 12:04:18 [2] => 2016-04-29 12:06:07 [3] => 2016-04-29 12:07:56 [4] => 2016-04-29 12:10:30 [5] => 2016-04-29 12:11:59 )
Usually I can do a foreach ($start_time as $time){} to itterate through all the values, but (correct me if I'm wrong) I can't put two array's into the foreach brackets and I can't place another foreach statement in the current one because then it will just return all the times for the second array and only return one value for the first array. I feel like I'm missing something simple, what can I do to accomplish this?
EDIT
Thanks to Scopey I've worked out a while loop, but it's not functioning correctly. Here is what I have:
$startTimes = array_column($startTimes, 'time');
$endTimes = array_column($endTimes, 'time');
while (($startTime = current($startTimes)) !== false && ($endTime = current($endTimes) !== false)) {
$startTimesConv = strtotime($startTimes);
$endTimesConv = strtotime($endTimes);
$totalTime = ($startTimesConv - $endTimesConv)/60/60;
next($startTimes);
next($endTimes);
}
If you want to loop two arrays at the same time, you can use the PHP functions for traversing arrays by manipulating their internal pointer: current, next, reset, end and prev.
You just need to make a while loop:
while (($startTime = current($startTimes)) !== false && ($endTime = current($endTimes) !== false) {
// ... Do things
next($startTimes);
next($endTimes);
}
See the documentation for next and current
To iterate two regular arrays with the same length use for instead of foreach:
$length = count($start_times);
for ($i = 0; $i < $length; $i++) {
$start_time = $start_times[$i]["time"];
$stop_time = $stop_times[$i]["time"];
// do things
}
But in your case, I strongly recommend that calculate the differences in SQL.
I would take a step back and look at the queries themselves. You are trying to do a calculation between two times which are related in your database however, the relationship gets lost by separating the times into two separate arrays. Or at the very least is ambiguously related as an array index.
My pseudocode would look like this:
#For each ticket which is closed
#Get an array (time entries) of arrays (start, stop) (each having it's start and stop time)
#total_time = 0
#For each time entry
#Perform a time calc function to get_time_differnce(start, stop)
#Add the time to Total_time
#Add total_time to ticket record in DB
If you showed some more detail I might be able to expand. (i.e The queries themselves)
Related
I'm creating a PostgreSQL table column management tool to quickly add, remove and rearrange columns in tables. Thus far it is working great in simple scenarios where I simply append a column to the end or remove an existing column. Each of my if conditions call other functions to append a new column, delete an existing column or to rebuild the table as a whole; these functions work great as far as I can currently test.
How do I create an if condition where I'll call both the append function and the delete function instead of the rebuild function?
I have several arrays to help me determine the logic though I'm having trouble getting it worked out. Here are the arrays of column names and again in this scenario I should not be calling the rebuild function, need to call the append function and the delete function.
In this scenario all I'm going to do is delete the column id_2 and add the column id_4 so there is no need to rearrange the order or columns.
$columns_db - The columns as they exist in the PostgreSQL database.
Array
(
[0] => id
[1] => id_1
[2] => id_2
[3] => id_3
)
$columns_updated - The columns in the database that we're going to keep.
Array
(
[0] => id
[1] => id_2
[2] => id_3
)
$columns_submitted - The final way the columns should appear when all is done,
Array
(
[0] => id
[1] => id_2
[2] => id_3
[3] => id_4
)
$columns_slice
$columns_slice = array_slice($columns_submitted,0,(count($columns_updated) - 1),true);
Array
(
[0] => id
[1] => id_2
)
$columns_remove - The column(s) that will be dropped.
Array
(
[1] => id_1
)
$columns_append - The column(s) that will be created.
Array
(
[id_4] => bigint
)
Perform column deletions first
implode column list after deletions ($before = implode($columns_updated);)
implode column list after additions ($after = implode($columns_submitted))
if (strpos($after, $before) === 0) { /* the additions are at the end */ }
Make sure you use the === operator.
As a one-liner:
$rebuild = (strpos(implode($columns_submitted), implode($columns_updated)) !== 0);
I generally prefer straight forward if / else if conditions though it seemed that it would be simply too wildly convoluted to maintain. #AbraCadaver had the good sense to keep the add/remove detection separate which I adapted (would have up-voted if it wasn't deleted). I've tested about a dozen tricky combinations and haven't been able to find any false-positives. Here is the debug version I used to help visualize the logic:
$rebuild = 0;
foreach ($columns_append as $k1 => $v1)
{
//echo '<div class="clear">k1 = '.$k1.'</div>';
if (in_array($k1,$columns_slice)) {$rebuild = 1; break;}
else
{
$columns_submitted_key = array_search($k1,$columns_submitted);
//echo '<div class="clear">columns_submitted_key: '.$columns_submitted_key.', $columns_updated count = '.count($columns_updated).'</div>';
if ($columns_submitted_key<count($columns_updated)) {$rebuild = 1; break;}//echo '<div class="error">Yeah, rebuild here.</div>';
}
}
if ($rebuild>0) {echo '<div class="clear">1, rebuild.</div>';}
else
{
if (count($columns_append)>0) {echo '<div class="clear">2,append</div>';}
if (count($columns_remove)>0) {echo '<div class="clear">3,delete</div>';}
}
My problem is easy to understand, I need to loop a table and calculate the average of every last 4 value. I try to use Queue to Push the current value and to pop the first value pushed.
I have 2 problem, The Queus works as Stack, when I pop, the last value goes out and not the first one
$q = new SplQueue();
$q->push(1);
$q->push(2);
$q->push(3);
$q->push(4);
$q->push(5);
$q->pop();
I get this Array as ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) )
I want this Array as ( [0] => 2 [1] => 3 [2] => 4 [3] => 5 ) )
Second problem, How to use array_sum($q) / $counter[$q]; on Queue ?
Thank you
As it is said in documentation (http://php.net/manual/ro/class.splqueue.php ), if you use push() and pop() it will behave like a stack. Use enqueue() and dequeue()
If you want to get the average of last 4 values, you can create a new array containing the 4 values of your queue dequeue(), then use array_sum($a)/ count($a) on it
If you do not want to create a new array you can simply:
$sum = 0;
$lastElements = 4;
for($i = 0;$i<$lastElements;$i++)
$sum+= $q.dequeue()
echo $sum/$lastElements;
And you can scale this by changing the $lastElements value.The code is not tested
Wondering if anyone can help with the following. Basically I have a form which allows users to select a start and end date, start time and end time.
The user can add time blocks, so they select the info they want, post it, then the page is returned, this happens until they process the form with the complete button.
The issue I am facing is, I need my array to append each post to my array, I have the following code:
if($this->input->post('submit', TRUE) == 'more')
{
$start_date = $this->input->post('start_date', TRUE);
$start_time = $this->input->post('start_time', TRUE);
$end_time = $this->input->post('end_time', TRUE);
$start_dates['start_date'] = $start_date;
$start_dates['start_time'] = $start_time;
$start_dates['end_time'] = $end_time;
if(isset($this->session->userdata['start_dates']) )
{
$merged = array_merge_recursive($start_dates, $this->session->userdata['start_dates']);
}
else
{
$merged = null;
$this->session->set_userdata('start_dates', $start_dates);
}
Problem is, each time we add a new time block one of the items in the array is overwritten.
The expected output for the array is:
Array
(
[start_date] => Array
(
[0] => 2012-08-31
[1] => 2012-08-29
)
[start_time] => Array
(
[0] => 08:00
[1] => 09:00
)
[end_time] => Array
(
[0] => 12:00
[1] => 17:00
)
)
Array key [1] is always overwritten in this case, if we add only two time blocks this would not be a problem - however the user needs to be able to add more than 2 blocks, total limit is up to user to a set limit we'll specify later.
Could anyone help get the logic sorted out.
Thanks in advance.
Mark
You need to save the merged data into the session too and the array merge should apply to the stored array in session:
if($this->session->userdata['start_dates'])
{
$merged = array_merge_recursive($this->session->userdata['start_dates'],
$start_dates);
}
else
{
$merged = $start_dates;
}
$this->session->set_userdata('start_dates', $merged);
I am pulling out a number of notes associated with a time from my database.
I'm not too hot with multidimensional arrays, but I'd like to group all the events together under the time that they occurred.
Here is one of my queries:
SELECT TIME(date) AS time, followupNote, completed, entityRef
FROM entity_followups
WHERE userRef = ?
AND DAY(date) = ?
AND MONTH(date) = ?
AND YEAR(date) = ?
An example output from this could be three rows, the first column being the time, then the note, completed, then the entityRef.
I want any rows with the same time to be grouped together in the array, e.g.
Array (
[0] => Array (
[0] => 12:00:00
[1] => Array (
[0] => note
[1] => completed
[2] => entityRef
)
[2] => Array (
[0] => note2
[1] => completed2
[2] => entityRef2
)
)
)
But later on there will be other queries that collect other kinds of events which need to be added into the top level array, and if an event has the same time as one in the subarray, it needs to be added into that.
I'll assume that your existing code is enough for getting the time and value. Thus you will have these items in whatever variable or data structure you choose to use. For the purposes of this answer, I will assume these values already exist in the individual variables: $time, $value[0], $value[1], and $value[2]. Further, I will assume that the results are being loaded into the array $timesAndValues[]
I think the key is to have the $timesAndValues[] array indexed on the corresponding time:
if (isset($timesAndValues[$time]))
{ //The corresponding sub-array already exists, so we just need to load it
//Push the array of values into the sub-array
array_push($timesAndValues[$time], $value);
}
else
{ //The corresponding sub-array does not exist yet, so we need to create it and load it
//Create the sub-array
$timesAndValues[$time] = array($time);
//Push the array of values into the sub-array
array_push($timesAndValues[$time], $value);
}
I am pulling some data from a mysql table via the following:
$result = mysql_query("SELECT characters_ID, name, borndate, deathdate, marrieddate, ispregnant FROM characters WHERE isfemale='1'",$db);
$femaledata = array();
while ($row_user = mysql_fetch_assoc($result))
$femaledata[] = $row_user;
This gives me an array that looks like this:
Array (
[0] => Array ( [characters_ID] => 2 [name] => Helene [borndate] => 35 [deathdate] => 431 [marrieddate] => 157 [ispregnant] => 0 )
[1] => Array ( [characters_ID] => 4 [name] => Isabelle [borndate] => 161 [deathdate] => [marrieddate] => 303 [ispregnant] => 1 )
[2] => Array ( [characters_ID] => 7 [name] => Helene [borndate] => 326 [deathdate] => [marrieddate] => [ispregnant] => 0 )
[3] => Array ( [characters_ID] => 72 [name] => Faylinn [borndate] => 335 [deathdate] => [marrieddate] => [ispregnant] => 0 )
[4] => Array ( [characters_ID] => 74 [name] => Relina [borndate] => 349 [deathdate] => [marrieddate] => [ispregnant] => 0 )
)
Now I need to remove any characters who have a value for deathdate or ispregnant, and then I need to run some code on the others. For instance I need to grab the borndate value, compare it to the current date to find age, and based partly on age, I need to run code for each to determine if the character has become pregnant on the turn.
Apologies that this seems like a long-reaching question. Multidimensional arrays still seem to confound me.
Edit: (question needs to be more clear)
Can you please suggest the best way that I would either explode or break up the array, and then do conditional modification to the data, or instead how I could remove unneeded data and then do conditional modification to the data.
My ultimate output here would be taking suitable female characters (not dead or pregnant already), and based on their age, giving them a chance at becoming pregnant. If true, I'd throw some code back at the SQL database to update that character.
Thanks!
All the things you need could probably get done with SQL :
Now I need to remove any characters who have a value for deathdate or
ispregnant
Simply add some argument to your WHERE condition :
isPregnant IS NULL AND deathdate IS NULL
For instance I need to grab the borndate value, compare it to the
current date to find age
Depending of your field format the maths could be done in SQL , have look to the DATE function of mysql
Don't underestimate the power of your sql server , 99% of the time it is probably faster than php to work on data set.
Instead if immediately removing some rows from your array, try limiting the data you recieve through SQL.
You can loop through your array like this:
foreach($femaledata as $female)
{
echo $female['name'];
}
do you mean something like this?
$femaledata = array();
while ($row_user = mysql_fetch_assoc($result)) {
$ok = false;
// do you validation for every user
if($ok) array_push($femaledata,$row_user);
}
TJHeuvel gave you the right answer, and you should accept that answer. However, to inform: multidimensional arrays need not confound. Let me see if I can explain.
In PHP, you can put any object at all into an array, including other arrays. So, let's say you have an array that contains other arrays. When you iterate over that array using a looping construct (usually a foreach loop), each iteration of the loop will give you another array; if you want to access the elements of this sub-array, just loop over it. This is called a nested loop. Example:
$r = array(
array(1,2,3),
array(4,5,6),
array(7,8,9)
);
foreach ($r as $cur) {
foreach ($cur as $num) {
echo $num;
}
}
In each iteration of the outer loop, $cur contains an array; the inner loop iterates over contents of this array. This technique allows you to process arrays of any dimension.
However, in your specific case, you don't need to use an inner loop to iterate over your subarrays. You only need to access certain elements of your subarrays by their keys, rather that processing all of them in turn. So, a simple foreach loop will do.