PHP Array_Unique Problem - php

I don't know PHP very well, so please bear with me.
My client has a database with information and one of the fields is ff_date_time in the format "Tue Oct 5 14:43:10 2010". There are a lot of entries in here and I need to display a list of just the days that have entries: ie, Tue Oct 5, 2010Thurs Oct 7, 2010 and so on. There may be hundreds of entries on a certain day, so obviously when I pull in dates from the db I need to go through and extract the right data and filter it. Here's what I have so far:
$query = "SELECT ff_date_time FROM booth_submit";
$query_result = mysql_query($query);
$datetimes = array();
$dates = array();
while ($row = mysql_fetch_array($query_result)) {
$datetimes[] = $row['ff_date_time'];
}
for ($i = 0; $i < sizeOf($datetimes); $i++) {
$temp = explode(" ", $datetimes[$i]);
$dates[] = ($temp[0]." ".$temp[1]." ".$temp[2]." ".$temp[4]); # Breaks date_time into 'Mon Oct 5 2010' format
}
$dates = array_unique($dates);
for ($i = 0; $i < sizeOf($dates); $i++) {
echo(''.$dates[$i].'<br />');
}
I'm doing a similar thing for two others fields that work fine, but for some reason, this always yields a $dates array that is the right length (ie: 4 unique dates, array is size 4), but only the first $dates element has any info. The output looks like this:
Mon Oct 3 2010<br />
<br />
<br />
<br />
When I don't use array_unique and just test values to check if everything is getting loaded and parsed correctly, the array is just as it should be ("Mon Oct 3 2010","Mon Oct 3 2010","Mon Oct 3 2010","Mon Oct 4 2010","Mon Oct 5 2010","Mon Oct 5 2010","Mon Oct 6 2010").
Any clues what's going wrong here?

array_unique preserves the keys so your resulting array has elements [0], [4] and [6].
I suggest using
foreach ($dates as $date) {
echo(''.$date.'<br />');
}

Assign the unique array to another array variable. And use foreach.
$newarr = array();
$newarr = array_unique($dates);
foreach ($newarr as $date) {
echo(''.$date.'<br />' . "\n");
}

I would rather recommend you another approach. Using the built-in datetime functions.
$all_dates = array();
foreach($datetimes as $date) {
$all_dates[] = date('D M j Y', strtotime($date));
}
$unique = array_unique($all_dates);

How about instead of treating the symptom, you remove the cause.
Add GROUP BY ff_date_time to the end of your query, or wrap DISTINCT() around ff_date_time in the select. Then you'll only get unique dates in your sql result.
edit: ok, assuming that ff_date_time is actually a datetime field, then in order to ignore time of day, make that GROUP BY DATE(ff_date_time) which will use only the day part and not the time part. If it's not a datetime field, and just a string, you will have to do substring functions, or use someone else's answer.

What is the output of var_dump($dates) after you used array_unique?
Try foreach instead of a for loop:
foreach($dates as $date) {
echo(''.$date.'<br />');
}

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 />';
}

Combining while in foreach in PHP

I have been working for a while to combine a "foreach loop" and a "while loop". I would like my foreach to run 30 times. This is indicated by $counter. Now the problem is that my "while" again starts the "foreach" every time. But it hears 30 times turning the "while" each time again.
If I get the while part away and use static code, it will work completely. But I need to link my DB for the information. Perhaps an option is to make a "foreach" a "for" or a whole different option. But I have no idea how to set him up.
$counter = days in a month
$index = foreach time for running. Max $counter
$NUM = unique number of 1 people
The $ index together with $ cut_startday together indicate when a box is to be red or green.
Here's the code for the none working foreach:
foreach(range(1,$counter) as $index) {/*open foreach*/
$get_data = "
SELECT *
FROM core";
$result1 = $conn->query($get_data) or die($conn ->error);
//Start query 1
if($result1) {
while($row = $result1->fetch_assoc()) {
// Get NUM, START DATE and END DATE
$NUM = ($row['c_m_num']);
$startdate = ($row['e_date_s']);
$enddate = ($row['e_date_e']);
// Cut strings for date
$sort_year = substr($startdate, 6, 4); // START YEAR -> 2017
$sort_month = substr($startdate, 0, 2); // START MONTH -> 09
$cut_startday = substr($startdate, 3, 2); // START DAY -> 17
$cut_endday = substr($enddate, 3, 2); // END DAY -> 19
if($load_m_NUM == "$NUM" and $index >= $cut_startday && $index <= $cut_endday ){
echo"<td style='background-color:red;'>x</td>";
}
else{
echo"<td style='background-color:green;'></td>";
}
}
}
/*end foreach*/ }
What the idea is of the code. I want a calendar with a top row de days of a month and on the left side al the people. If the core find a match between days and 1 men, color the td red if not color green.
Any help greatly appreciated!
You could change the foreach statement to for ($index = 0; $index < 30; $index++). To improve your code I suggest putting the for loop inside the while loop instead. That way you only query the database once instead of 30 times.

PHP data retrieval in array

I have one table having columns:
S.NO month year total
1 jan 2017 1000
2 feb 2017 5000
3 jan 2018 3000
I want to fetch data and arrange in such a way that total values of similar months are added and store in key value pair in array using PHP.
There will be data only for years.
e.g.
2017 -> 6000
2018-> 3000 and so on.
Thanks in advance!
Assuming the table structure is like this,
The query should be
SELECT SUM(tt),yr FROM t1 GROUP BY yr
Sample output :
In PHP in the while loop just,
use something like,(just giving a sample, not the full thing)
while($row = mysqli_fetch_assoc($results))
$array[$row['yr']] = $row['SUM(tt)'];
Please try -
$result = mysql_query("SELECT * FROM test1");
$newarray = array();
$i = 1;
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
if($i==1){
array_push($newarray, array("year"=>$row["year"], "total"=>$row["total"]));
}else{
$sr = array_search($row["year"], array_column($newarray, 'year'));
if($sr === false){
array_push($newarray, array("year"=>$row["year"], "total"=>$row["total"]));
}else{
$newarray[$sr]["total"]+=$row["total"];
}
}
$i++;
}
print_r($newarray);

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.

How to break up reports by month with php and mysql?

I'm trying to do something relatively simple here. Basically I have a table with a bunch of rows in it marked with a timestamp (format: 2009-05-30 00:14:57).
What I'm wanting to is do is a query which pulls out all of the rows, and splits them by the month so I'm left with a final result like:
February
rowID name order date
rowID name order date
rowID name order date
January
rowID name order date
rowID name order date
rowID name order date
etc.
I have a few vague ideas how to do this - they just seem long winded.
One of the ways would be to do a query for each month. I'd derive what the current month is in PHP then construct a for() which goes back a certain number of months.
like:
$currentmonth = 8;
$last6months = $currentmonth - 6;
for($i = $currentmonth; $i == $last6months; $i--) {
$sql = 'SELECT * FROM reports WHERE MONTH(reports.when) = $currentmonth ';
$res = mysql_query($sql);
// something would go here to convert the month numeral into a month name $currentmonthname
echo $currentmonthname;
while($row = mysql_fetch_array($res)) {
// print out the rows for this month here
}
}
Is there a better way to do this?
It's better to fetch all data once,ordered by month..
Then while fetching with php you can store your current month in a variable (for example $curMonth) and if there is a change in the month, you echo "New Month"...
Executing a query is slow, it's better to minimize your "conversations" with the db..
Don't forget that you have to deal with years aswell. If you have two records, one for January '09 and one for January '08, your results may be skewed.
Best to follow Svetlozar's advice and fetch all data at once. Once you have it in memory, use PHP to segment it into something usefull:
$monthData = array();
$queryResult = mysql_query("
SELECT
*,
DATE_FORMAT('%m-%Y', when) AS monthID
FROM
reports
WHERE
YEAR(when) = 2009 AND
MONTH(when) BETWEEN 5 and 11
");
while ($row = mysql_fetch_assoc($queryResult))
{
if (!isset($monthData[$row['monthID']]))
$monthData[$row['monthID']] = array();
$monthData[$row['monthID']][] = $row;
}
mysql_free_result($queryResult);
foreach($monthData as $monthID => $rows)
{
echo '<h2>Data for ', $monthID, '</h2>';
echo '<ul>';
foreach($rows as $row)
{
echo '<li>', $row['someColumn'], '</li>';
}
echo '</ul>';
}
You could change your SQL query to get your entire report. This is much more efficient than querying the database in a loop.
select
monthname(reports.when) as currentmonth,
other,
fields,
go,
here
from reports
order by
reports.when asc
You could then use this loop to created a nested report:
var $currentMonth = '';
while($row = mysql_fetch_array($res)) {
if($currentMonth !== $row['currentMonth']) {
$currentMonth = $row['currentMonth']);
echo('Month: ' . $currentMonth);
}
//Display report detail for month here
}
*Note: Untested, but you get the general gist of it I'm sure.
This is the SQL script:
SELECT*, DATE_FORMAT(fieldname,'%Y-%m') AS report FROM bukukecil_soval WHERE MONTH(fieldname) = 11 AND YEAR(fieldname)=2011
I hope you know where you should put this code :D

Categories