Adding rows to an array in PHP - 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.

Related

How to count sum of values from json objects in certain subdirectories seperately

I have 3 directories named september, october and november in the maindirectory 2021.
In all these 3 directories are json files which look like this:
{
"id": "id_2021-09-05_2200",
"date": "2021-09-05",
"guests": 32 // total guests for that day
}
For every month, i need the sum of all guests for that month. ( count all guests from all the json files in that month together).
I have this code so far but i get stuck in counting for each month:
$monthdirs = array_filter(glob('data/2021/*'), 'is_dir'); // read all month-dirs in year 2021
foreach($monthdirs as $monthdir) {
$monthfiles = glob($monthdir.'/*.json'); // all json files in a specific month
}
foreach($monthfiles as $monthfile) {
$arr[] = json_decode(file_get_contents($monthfile),true); // php assoc array
foreach($arr as $key => $val) {
$tot_guests_monthes[] += $val['guests']; // new array from each month with the sum of guests from all the json files in that month
}
}
foreach($tot_guests_monthes as $tot_guests_month) {
echo $tot_guests_month.'<br />';
}
I think in the 2nd foreach loop i am doing something wrong. My final output should be 3 values, something like:
200 // all guests september
300 // all guests october
400 // all guests november
$...[] = is basically a array_push, which means that $tot_guests_monthes[] += $val['guests']; will create a new element for each element of $arr of each $monthfile instead of summing.
Summing all values in a month and then adding them to $tot_guests_monthes should work:
$tot_guests_monthes = [];
$monthdirs = array_filter(glob('data/2021/*'), 'is_dir'); // read all month-dirs in year 2021
foreach($monthdirs as $monthdir) {
$monthfiles = glob($monthdir.'/*.json'); // all json files in a specific month
$sum = 0;
foreach($monthfiles as $monthfile) {
$arr = json_decode(file_get_contents($monthfile), true);
$sum += $arr['guests'];
}
$tot_guests_monthes[] = $sum;
}
foreach($tot_guests_monthes as $tot_guests_month) {
echo $tot_guests_month.'<br />';
}

how to count the days (mon,tue) from unix time in an array?

I have an array name,unixtime,page.
I am gathering stats and would like to know the days (mon,tues,wed) on which pages are looked at. I have already done this with the username (bob viewed 3 pages) using the using array_count_values() function. However I would have to convert the unix time into date('D',$unixtime); Without going into loops is there a clever way of doing this.
So this is my base code for counting the pages the user viewed. I now want to count the days on which page was viewed.
// Get number of times user requested a page
$user_request_array = array();
$user_request_array = array_count_values(array_column($array, 0));
arsort($user_request_array);
$user_request_key_array = array_keys($user_request_array);
$y = 0;
foreach ($user_request_array as $user_request_stat_line) {
$user_request_stats .= $user_request_key_array[$y].':
<strong>'.$user_request_stat_line.'</strong><br>';
$y++;
}
Any ideas on doing this in a clever way or do I start looping?
Thanks.
So this is how I decided to do it in the end.
## I have a loop here creating tables from the data so...
// While we are here in the loop get the unix date and convert to day
$day_request_flat .= date('D',$log_line[5]).',';
}
// Create day stats.
$day_request_array = array(); // Define the array
$day_request_flat = rtrim($day_request_flat,','); // Remove the last comma
$day_request_array = explode(',', $day_request_flat); // make an array out of the comma separated variable.
$day_request_array = array_count_values($day_request_array); // Count stuff in the array
$day_request_key_array = array_keys($day_request_array);
$y = 0;
foreach ($day_request_array as $day_request_stat_line) {
$day_request_stats .= $day_request_key_array[$y].': <strong>'.$day_request_stat_line.'</strong><br>';
$y++;
}

PHP function - output of function is the input of another function

I have the following function where certain inputs are given and then 4 outputs are given: -
function rsiNext($dailyGainAvgPrev, $dailyLossAvgPrev,$cpDailyNext){
if($cpDailyNext > 0){
$dailyGainAvgNext = (($dailyGainAvgPrev * 13) + $cpDailyNext)/14;
}else{
$dailyGainAvgNext = (($dailyGainAvgPrev * 13) + 0)/14;
}
if($cpDailyNext < 0){
$dailyLossAvgNext = (($dailyLossAvgPrev*13) + abs($cpDailyNext))/14;
}else{
$dailyLossAvgNext = (($dailyLossAvgPrev*13) + abs(0))/14;
}
$relStrNext = $dailyGainAvgNext/$dailyLossAvgNext;
if($dailyLossAvgNext == 0){
$relStrIndNext = 100;
}else{
$relStrIndNext = 100-(100/(1+$relStrNext));
}
return array($dailyGainAvgNext, $dailyLossAvgNext, $relStrNext, $relStrIndNext);
}
I output the values using the following line of code:
//Get value for day 15
list($dailyGainAvg02, $dailyLossAvg02, $relStr02, $relStrInd02) = rsiNext($averageGains14, $averageLosses14, $priceDifferences[15]);
echo '<tr><td>'.$dailyGainAvg02.'</td><td>'.$dailyLossAvg02.'</td><td>'.$relStr02.'</td><td>'.$relStrInd02.'</td></tr>';
Now when I want the value for day 16 I use the following line of code:
//Get value for day 16
list($dailyGainAvg03, $dailyLossAvg03, $relStr03, $relStrInd03) = rsiNext($dailyGainAvg02, $dailyLossAvg02, $priceDifferences[16]);
echo '<tr><td>'.$dailyGainAvg03.'</td><td>'.$dailyLossAvg03.'</td><td>'.$relStr03.'</td><td>'.$relStrInd03.'</td></tr>';
The output of day 15 is the input of day 16, the output of day 16 is the input of day 17. The output of day 17 is the input of day 18, etc...
I need to repeat the list for 100 days. How can I go about it without repeating the list line for another 100 days?
Thank you.
Assuming you have the $priceDifferences array fully populated, something like the following should do:
$cur_dailyGainAvg = 0; // you need to initialize this value appropriately
$cur_dailyLossAvg = 0; // you need to initialize this value appropriately
for ($idx = 1; $idx <= 100; $idx++) {
list($new_dailyGainAvg, $new_dailyLossAvg, $new_relStr, $new_relStrInd) = rsiNext($cur_dailyGainAvg, $cur_dailyLossAvg, $priceDifferences[$idx])
// print
echo '<tr><td>'.$new_dailyGainAvg.'</td><td>'.$new_dailyLossAvg.'</td><td>'.$new_relStr.'</td><td>'.$new_relStrInd.'</td></tr>';
// shift the new values onto the current, and repeat the calculation
$cur_dailyGainAvg = $new_dailyGainAvg;
$cur_dailyLossAvg = $new_dailyLossAvg;
}
Basically distinguish between your "current" values, which you feed into your function, and the "new" values that come out, then "shift" the new onto the current ones and repeat.
You may have to check the boundaries of the loop.

do-while in php resulting a non-stop page loading

I want to have a $startdate counting 3 days backward from an input date by user, where those 3 days are not holidays.
So if the input date by user is October 22, the $startdate would be October 17 instead of October 19. Because October 19 and 20 are holidays
$i = 1;
do{
//some code to produce the $startdate
//...
//end
//check if $startdate is holiday or not
$this->db->where('hl_date',$startdate);
$query = $this->db->get('php_ms_holiday');
//if $startdate = holiday, it doesn't count
if($query->result_array()){
}
else{
$i++;
}
}while($i <= 3);
But, with that code I have a non-stop loading on the browser when a $startdate captured inside the if($query->result_array()) statement. And the browser can only returning results when I put something like this code below, inside the if($query->result_array()) statement:
$i = $i + n; //n is a number starting from 1, or
$i++;
but not:
$i = $i; //or
$i = $i + 0;
Why is that?
You just make a DB query which result interprets as TRUE. Maybe I wrong but it seems you are make the same db query in each loop iteration.
So, check your query, for example add specific date for holiday checking.
if($query->result_array()) will always evaluate to true, if your query is correctly formulated. So also if the number of rows returned is 0. This means that you never ever go to the else. You if-statement should check the number of results returned instead; Furthermore, I personally would prefer a normal for-loop:
for($i = 0; $i < 3)
{
//some code to produce the $startdate
//...
//end
//check if $startdate is holiday or not
$this->db->where('hl_date',$startdate);
$query = $this->db->get('php_ms_holiday');
//if $startdate = holiday, it doesn't count
if [num_rows equals 0] // test num_rows here; Not sure what your class offers here
{
$i++; // increment counter
// do whatever else you want to do
}
}
If this is always true:
if($query->result_array()){
}
Then this will always be true:
}while($i <= 3); //$i is never adjusted, so it will always be less than 3
Since you say that you want to display data from with the last 3 days but if there are holidays in between, you don't want to count them. To get around this I think you should not use the literal "3" since it can be adjusted, it should be a variable too.
A possible solution would be to have a variable such as:
$days_back = 3;
Then try to count the amount of holidays within the last 3 days(or something like that):
//You can make the holidays to be zero by default
$holidays = someWayToCountHolidays($startDate, $endDate); //You'll obviously have to code this
Then you can make make the variable your while loop will work agains
$num_days = $days_back + $holidays; //$holidays can be zero by default
Then something like below for you do while loop:
if($query->result_array()){
//Then do what ever you want to do here
} else {
//Then do what ever you want to do here
}
$i++; //Adjust $i
}while($i <= $num_days);

Dynamic X-axis graph that will change according to the count of rows

Let's say I have a mysql table with an id, some measurements and a DATE column.
Example: id, measurements, date_entered
This table stores some measurements of a patient so as to keep a record for him.
I want to make a graph which according to the count of rows that exist in the database will change dynamically the X-axis.
For example, if there are only 7 rows in the table I need to represent 7 days to the graph with the measurement for every day. If there are more than 14 days, I want it to change to respresent 2 weeks on X-axis and the average measurements(average for 1 week and average for the other too) on Y-axis and so on from weeks to months.
Can anyone help me on this? I cannot think of something that will do in my case..
I use JPGraph to make the line graph but i don't have a problem there. My problem is on how to handle the results.
I hope you will understand what I need! Thanks.
Something like this?
// Get the results from the database
$query = "SELECT `data_col` FROM `table` WHERE `condition_col` = 'some value'";
$result = mysql_query($query);
// Get all results into array and count them
$results = array();
for ($i = 0; $row = mysql_fetch_assoc($result); $i++) {
$results[] = $row;
}
// Re-format the data depending on number of results
$data = array();
if ($i < 14) { // Less than 14 days, show per day
foreach ($results as $row) {
$data[] = $row['data_col'];
}
} else if ($i < 56) { // Less than 8 weeks, show per-week
$thisweek = array();
for ($j = 0; isset($results[$j]); $j++) { // Loop the results
$thisweek[] = $results[$j]['data_col']; // Add result to this week total
if ($j % 7 == 0 && $j > 0) { // Every 7 days...
$data[] = array_sum($thisweek) / 7; // ...calculate the week average...
$thisweek = array(); // ...and reset the total
}
}
// If there is an incomplete week, add it to the data
$data[] = array_sum($thisweek) / count($thisweek);
} else { // 8 weeks or more, show per-month
$thismonth = array();
for ($j = 0; isset($results[$j]); $j++) { // Loop the results
$thismonth[] = $results[$j]['data_col']; // Add result to this month total
if ($j % 28 == 0 && $j > 0) { // Every 28 days...
$data[] = array_sum($thismonth) / 28; // ...calculate the month average...
$thismonth = array(); // ...and reset the total
}
}
// If there is an incomplete month, add it to the data
$data[] = array_sum($thismonth) / count($thismonth);
}
// $data now contains an array from which you should be able to draw your
// graph, where array keys are (sort of) x values and array values are y
// values.
Obviously, this solution assumes a 28-day month - it does not use the calendar, simply the number of days. You could do something horrible involving working out the stats based on some values returned by date() or similar, but this would likely drastically increase the calculation overhead and slow the process down.
Hopefully this will give you a place to start.

Categories