I have this array data structure:
$records = [];
$records[] = ['id' => 1, 'date' => '2017-03-12', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-13', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-13', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-14', 'operation' => 'forgot_password'];
$records[] = ['id' => 1, 'date' => '2017-03-14', 'operation' => 'sent_email'];
$records[] = ['id' => 2, 'date' => '2017-03-14', 'operation' => 'sent_email'];
$records[] = ['id' => 2, 'date' => '2017-03-14', 'operation' => 'forgot_password'];
$records[] = ['id' => 1, 'date' => '2017-03-27', 'operation' => 'sent_email'];
$records[] = ['id' => 1, 'date' => '2017-03-29', 'operation' => 'sent_email'];
In this array I store operations that were done by website visitors. Obviously visitor can be identified by an id number.
What I want to do is to count how many times in a week (between Monday and Sunday inclusively) each visitor used 'sent_email' operation.
For example: first record with 'sent_email' operation shows that this operation happened in '2017-03-12' (Sunday), so that means this operation took place just once in that week for user with an id = 1.
Other next three 'sent_email' operations for user with an id = 1 happened three times in another week. (2017-03-13, 2017-03-13, 2017-03-14 those three dates belong to the same week).
I know that I probably need to loop through each record and somehow to check those dates if they belong to the same week, but I feel confused and stuck here, I don't understand logical steps needed to accomplish it. I would be really grateful if anyone could give me an explanation or pseudo code, whatever it is that would help me to tackle this problem, I really enjoy solving problems myself but because I'm stuck, I just need someone to get me up and running.
Thank you in advance for any help you can provide.
The DateTime object and the strtotime() functions both understand relative date strings, so you can do neat things like "last tuesday" and "3 days ago".
Some pseudo-code to get you started:
// figure out when your monday is
monday = ...
// figure out when your sunday is
sunday = ...
// loop over all records
foreach $record:
// skip records outside the date range you want
if date < monday or date > sunday then skip this record;
// skip records not of the type you want
if operation != email then skip this record;
// register a hit for this user
increment counter for user
Related
I'm trying to add a year feature in my code.
Here, I push the years in an array, which can be selected after, using a select
$years = 2020;
$years_array = array();
// up-to-date years in array, starting from year 2020
while ($years <= date('Y'))
{
$to_push = array(strval($years)=>$years);
array_push($years_array, $to_push);
$years++;
}
$choices = array_values($years_array);
Then, I add them to the builder (I also show you the months, this has been developed by someone before me)
->add('mois', ChoiceType::class, [
'choices' => [
'Janvier' => 1,
'Février' => 2,
'Mars' => 3,
'Avril' => 4,
'Mai' => 5,
'Juin' => 6,
'Juillet' => 7,
'Aout' => 8,
'Septembre' => 9,
'Octobre' => 10,
'Novembre' => 11,
'Décembre' => 12
],
'data' => date('n')
])
->add('annee', ChoiceType::class, [
'choices' => $choices,
'data' => date('Y')
It works fine, I get the year afterwards, and the text shows up in the Select tag.
But I see the indexes of the array, as shown in this picture, which looks terrible.
How could I take these off?
You're nesting the associative arrays into an indexed array. You should just assign directly to indexes of $years_array.
for ($year = $years; $year < date('Y'); $year++) {
$years_array[$year] = $year;
}
You don't need to use array_values() afterward.
I'm trying to make an calendar scheduler for student teacher for their future lessons together.
I'm trying to add day, time and DATE(most important). Right now I added day and time in each of their following meetings. For ex. every Monday at 08:00 and every Wednesday at 10:00. But what I cannot add is Date . Here is some of my coding.
$student = Auth::user()->student;
$teacher = Teacher::where('id',$id)->first();
$lessons = $request->lessons_booked;
$times = $request->times;
$timesArrLength = count($times);
$stuTeachArr = array();
for($i = 1;$i<= $lessons;$i++){
$studentTeacher = StudentTeacher::create([
'student_id' => $student->id,
'teacher_id' => $teacher->id,
'subject_id' => $request->subject_id,
'place_of_tutoring_id' => $request->place_of_tutoring_id,
'lessons_booked' => $lessons,
'lesson_nr' => $i,
'time_id' => $times[($i-1) % $timesArrLength]['id'],
'day' => $times[($i-1) % $timesArrLength]['day'],
'date' => '2021-01-01', // add date here
'lessons_left' => $request->lessons_booked - $i,
'status' => 'active'
]);
array_push($stuTeachArr,$studentTeacher);
}
// $stuTeachArr['booked_teacher'] = $studentTeacher;
return $stuTeachArr;
What I want is to add DATE for every lesson that will happen from now until they finish with their lessons(For ex. every Monday and every Wednesday as mentioned before).
Any suggestion to change the way I'm doing would be welcomed.
I posted a question some time ago on representing data per date horizontally on a datatable.
See here: datatables dates at the top and data cells going from left to right
With the help of that thread I was able to get the data to display how I wanted it. With the dates showing at the top, the service provided on the left and all data associated with any date between the 2 date paramters inside the main body. (If there is no data in a particular date then the < td > will display 0. See here:
http://www.phpwin.org/s/ewbAS6
After manipulating this code further I made the dates of the search dynamic by proving a form with a start date and an end date, and a dropdown with the options of:
Daily
Weekly
Monthly
Quaterly
Yearly
this allows the interval of dates at the top to become dynamic. Of course all this is doing is changing the value of the 2nd parameter inside the date while loop.
WHILE (strtotime($date) <= strtotime($end_date)) {
echo '<th>' . $date . '</th>';
$date = date('Y-m-d', strtotime($date . ' +1day'));
}
with the parameter set at Weekly, the value of +1day becomes +1week, at Monthly; the value becomes +1month and so on.
MY ISSUE:
When the interval is set to daily, the dates with their corresponding attendance counts are displayed correctly but once you try to increase the interval to +1week and above the data does not round up to the week shown. Check this:
[LINK1]Per day: http://www.phpwin.org/s/ewbAS6
[LINK2]Per month: http://www.phpwin.org/s/xRo3I6
Looking at the array (modified on the LINK2)
$result[] = array('Service Name' => 'Health', 'date' => '2017-04-04', 'Attendance' => 5);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-16', 'Attendance' => 5);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-04-03', 'Attendance' => 1);
$result[] = array('Service Name' => 'Saturday Youth Meeting', 'date' => '2017-05-03', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-05-03', 'Attendance' => 2);
$result[] = array('Service Name' => 'Payroll', 'date' => '2017-04-11', 'Attendance' => 3);
$result[] = array('Service Name' => 'Payroll', 'date' => '2018-04-03', 'Attendance' => 10);
You can see in the array that there are multiple attendance entries in April, totaling 14 Attendances in that month however during LINK2 where the interval is increased to a month instead of showing 14 for April (which would be the sum of all the dates in that particular month) it shows the value 1.
My live version takes the array from a database so I used the YEAR(), MONTH(), WEEK() and DAY() function on the date and used group by. The query executes how I want it but having issues working on the PHP end.
I need to do a query and get certain kind of data. I have 2 tables, users and connections, I need to get per user how many times he/she connected per month and year.
users connections
........... ................
john 10/02/2014
john 15/02/2014
john 03/01/2015
john 06/02/2015
Is there a chance to get this info in this format:
john=>
[0]=>2014
[0]=>02
'total' =>2
[1]=>2015
[0]=>01
'total' => 1
[1]=>02
'total' => 2
[2]=>03
'total'=> 1
I'm using Codeigniter and also PHP.
Answering to #CodeGodie what I've done so far is:
public function getPeriodicity(){
$this->db->select('u.vusr_user, extract (MONTH from (to_timestamp(c.vuc_log_in))) as month, extract (YEAR from (to_timestamp(c.vuc_log_in))) as yearly, COUNT(c.vuc_log_in)');
$this->db->from('vts_users_conn c');
$this->db->join('vts_users u', 'c.vuc_vusr_id = u.vusr_id');
$this->db->group_by('u.vusr_user, month, yearly','asc');
$query = $this->db->get();
return $query->result_array();
}
Assuming you are using Codeigniter's $this->db->result_array() to obtain your database results, your initial array will look like this:
$res = array(
array(
"name" => "john",
"date" => "10/02/2014"
),
array(
"name" => "john",
"date" => "15/02/2014"
),
array(
"name" => "john",
"date" => "03/01/2015"
),
array(
"name" => "john",
"date" => "06/02/2015"
),
array(
"name" => "john",
"date" => "06/03/2015"
)
);
In order to change this array to your desired output, I would do the following:
foreach ($res as $row) {
$date_arr = explode("/", $row['date']);
$n = $row['name'];
$y = $date_arr[2];
$m = $date_arr[1];
if (!isset($final[$n]))
$final[$n] = array();
if (!isset($final[$n][$y]))
$final[$n][$y] = array();
if (!isset($final[$n][$y][$m])) {
$final[$n][$y][$m] = array("total" => 1);
} else {
$final[$n][$y][$m]["total"] = $final[$n][$y][$m]["total"] + 1;
}
}
If you var_dump your final result (var_dump($final)), you will get the following:
array (size=1)
'john' =>
array (size=2)
2014 =>
array (size=1)
'02' =>
array (size=1)
'total' => int 2
2015 =>
array (size=3)
'01' =>
array (size=1)
'total' => int 1
'02' =>
array (size=1)
'total' => int 1
'03' =>
array (size=1)
'total' => int 1
Hope this helps.
As a general rule, if you can access the data and see in your mind how you want that data to look, then it's pretty much possible to get it to do that. It's just a matter of working out the process.
In your case, I would do the following steps:
Order the data by users, then by date so everything is nicely together
Loop through the data and each time, check that the current user is the same as the last one. if it's not, create a new array key
split the date into the parts you want
check the user array for the key relating to year for that user. If the year exists, search for the month. If the month exists, add 1 to the total for that month. If the year and/or month don't exist, create the keys and set the total to be 1 for that month
Once the records have been processed, you should have the data in the format you need.
How do I find all by primary key? I don't want to specify the start and end dates as they aren't relevant when opening within booking form
$bookingRoom = BookingRoom::model()->findByPk(array('roomId' => 1, 'bookingId' => 1, 'startDate' => '20140619', 'endDate' => '20140620'));
You should use the findAllByAttributes() option:
$bookingRoom = BookingRoom::model()->findAllByAttributes(array('roomId' => 1, 'bookingId' => 1, 'startDate' => '20140619', 'endDate' => '20140620'));
If you don't want the startDate and endDate included remove it from the array.
Here is the documentation:
http://www.yiiframework.com/doc/api/1.1/CActiveRecord#findAllByAttributes-detail
you can try this:
$id = // code to set the id
$bookingRoom = BookingRoom::model()->findAllByPk($id);