PHP Create array using Loop and add days with zero orders - php

I have a mysql query output that give the number of loads for each day of the month.
Array
(
[0] => Array
(
[day] => 01
[Loads] => 9
)
[1] => Array
(
[day] => 02
[Loads] => 7
)
[2] => Array
(
[day] => 03
[Loads] => 12
)
[3] => Array
(
[day] => 04
[Loads] => 5
)
[4] => Array
(
[day] => 06
[Loads] => 1
)
[5] => Array
(
[day] => 07
[Loads] => 4
)
[6] => Array
(
[day] => 08
[Loads] => 9
)
[7] => Array
(
[day] => 09
[Loads] => 19
)
[8] => Array
(
[day] => 10
[Loads] => 11
)
[9] => Array
(
[day] => 11
[Loads] => 5
)
[10] => Array
(
[day] => 12
[Loads] => 2
)
[11] => Array
(
[day] => 14
[Loads] => 7
)
[12] => Array
(
[day] => 15
[Loads] => 9
)
[13] => Array
(
[day] => 16
[Loads] => 11
)
[14] => Array
(
[day] => 17
[Loads] => 9
)
[15] => Array
(
[day] => 18
[Loads] => 6
)
[16] => Array
(
[day] => 19
[Loads] => 3
)
)
You can see from the output not all days have loads. Day 5 and Day 13 are missing. I want to loop and create a new array and if there are no loads for that day add the day with zero loads.
I have been struggling with this. It seems that it would be simple but I can't seem to get it. Can someone here please help me?
I am extremely thankful.
Here is what I have so far:
$dayCountArr = [];
for ($i = 1; $i <= 31; $i++) {
$tempArr = [];
foreach ($dayO as $d) {
if ($d['day'] == $i) {
$day = $d['day'];
$loads = $d['Loads'];
} else {
$day = $i;
$loads = 0;
}
$dayCountArr[] = [$day, $loads];
}
}
Here is query. It returns the above output
SELECT
DATE_FORMAT(r.ship_date, '%d') AS day,
COUNT(DISTINCT(r.order_number)) AS 'Loads'
FROM table r
WHERE YEAR(r.ship_date) = '2022'
&& MONTH(r.ship_date) = 3
&& r.team = 'TEAM-2'
&& (r.order_status = 'Progress' || r.order_status = 'Delivered')
GROUP BY DATE_FORMAT(r.ship_date, '%d')

I assume your sql array is in $dayO and days are in preceding 0 format, I created load array for available days and assigned them to new dayCountArray. I applied str_pad to avoid keys 1(numeric) and use 01(string)
$dayCountArr = array();
foreach($dayO as $day){
$load[str_pad($day['day'], 2, "0", STR_PAD_LEFT)] = $day['Loads'];
}
for ($i = 1; $i <= 31; $i++) {
//Generating keys ('01','02',..,'31')
$key = str_pad($i, 2, "0", STR_PAD_LEFT);
//Assign 0 if Loads not available for $key
$dayCountArr[] = array('day' => $key,'Loads' => isset($load[$key])?$load[$key]:0);
}
print_r($dayCountArr);

Related

how to display PHP Multidimensional Arrays?

how to display this using foreach in php?
I want to show it as a list.
$quantity=0;
$quantities = array(
array('Jan',($quantity += $ppmpitem->m1)),
array('Feb',($quantity += $ppmpitem->m2)),
array('Mar',($quantity += $ppmpitem->m3)),
array('Apr',($quantity += $ppmpitem->m4)),
array('May',($quantity += $ppmpitem->m5)),
array('Jun',($quantity += $ppmpitem->m6)),
array('Jul',($quantity += $ppmpitem->m7)),
array('Aug',($quantity += $ppmpitem->m8)),
array('Sep',($quantity += $ppmpitem->m9)),
array('Oct',($quantity += $ppmpitem->m10)),
array('Nov',($quantity += $ppmpitem->m11)),
array('Dec',($quantity += $ppmpitem->m12)),
);
return $quantities;
You have several options, so based on your code (and what I added):
<?php
$quantity=0;
// Added this, so we have an object
$array = [
"m1" => 1,
"m2" => 2,
"m3" => 3,
"m4" => 4,
"m5" => 5,
"m6" => 6,
"m7" => 7,
"m8" => 8,
"m9" => 9,
"m10" => 10,
"m11" => 11,
"m12" => 12
];
// Converted array to object
$ppmpitem = json_decode(json_encode($array));
$quantities = array(
array('Jan',($quantity += $ppmpitem->m1)),
array('Feb',($quantity += $ppmpitem->m2)),
array('Mar',($quantity += $ppmpitem->m3)),
array('Apr',($quantity += $ppmpitem->m4)),
array('May',($quantity += $ppmpitem->m5)),
array('Jun',($quantity += $ppmpitem->m6)),
array('Jul',($quantity += $ppmpitem->m7)),
array('Aug',($quantity += $ppmpitem->m8)),
array('Sep',($quantity += $ppmpitem->m9)),
array('Oct',($quantity += $ppmpitem->m10)),
array('Nov',($quantity += $ppmpitem->m11)),
array('Dec',($quantity += $ppmpitem->m12)),
);
// Pretty print
print("<pre>".print_r($quantities,true)."</pre>");
// As a list where Month is key
foreach($quantities as $key => $value) {
$month = [
$quantities[$key][0] => $quantities[$key][1]
];
$months[$quantities[$key][0]] = $quantities[$key][1];
print_r($month);
}
//Also print full array of months:
print_r($months);
Results are:
Pretty print:
<pre>Array
(
[0] => Array
(
[0] => Jan
[1] => 1
)
[1] => Array
(
[0] => Feb
[1] => 3
)
[2] => Array
(
[0] => Mar
[1] => 6
)
[3] => Array
(
[0] => Apr
[1] => 10
)
[4] => Array
(
[0] => May
[1] => 15
)
[5] => Array
(
[0] => Jun
[1] => 21
)
[6] => Array
(
[0] => Jul
[1] => 28
)
[7] => Array
(
[0] => Aug
[1] => 36
)
[8] => Array
(
[0] => Sep
[1] => 45
)
[9] => Array
(
[0] => Oct
[1] => 55
)
[10] => Array
(
[0] => Nov
[1] => 66
)
[11] => Array
(
[0] => Dec
[1] => 78
)
)
</pre>
Print out "list":
Array
(
[Feb] => 3
)
Array
(
[Mar] => 6
)
Array
(
[Apr] => 10
)
Array
(
[May] => 15
)
Array
(
[Jun] => 21
)
Array
(
[Jul] => 28
)
Array
(
[Aug] => 36
)
Array
(
[Sep] => 45
)
Array
(
[Oct] => 55
)
Array
(
[Nov] => 66
)
Array
(
[Dec] => 78
)
Or print one array (month as key)
Array
(
[Jan] => 1
[Feb] => 3
[Mar] => 6
[Apr] => 10
[May] => 15
[Jun] => 21
[Jul] => 28
[Aug] => 36
[Sep] => 45
[Oct] => 55
[Nov] => 66
[Dec] => 78
)
BR
You may create an array filled from 1 to 12 and apply the array_reduce to get your output.
<?php
class P {
public $m1 = 1;
public $m2 = 1;
public $m3 = 1;
public $m4 = 1;
public $m5 = 1;
public $m6 = 1;
public $m7 = 1;
public $m8 = 1;
public $m9 = 1;
public $m10 = 1;
public $m11 = 1;
public $m12 = 1;
public function __construct() {
}
}
$ppmpitem = new P();
$array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
$quantities = array_reduce($array, function ($carry, $item) use ($ppmpitem) {
$month = DateTime::createFromFormat('!m', $item)->format('M');
$carry['total'] += $ppmpitem->{"m" . $item};
$carry['quantities'][] = [$month, $carry['total']];
return $carry;
}, ['total' => 0, 'quantities' => []])['quantities'];
var_dump($quantities);
There are a number of ways to display a multidimensional array including use of the default PHP's print_r() function. Besides if you want a more precise way of accessing the elements and displaying them you can use a looping criteria such as for() or foreach(). Sample :
foreach($quantities as $qty){
print_r($qty);
}

Replace the values ​of one array based on the values in another array

I have the following array
$priceYear = Array (
[AZ] => Array
(
[1] => 2020
[2] => 2020
)
[BY] => Array
(
[0] => 2020
[1] => 2020
)
[CX] => Array
(
[1] => 2020
[2] => 2020
[3] => 2020
)
[DW] => Array
(
[106] => 2019
[107] => 2019
[108] => 2019
)
)
And another array with this
$array = Array (
[0] => Array
(
[YEAR] => 2018
[VALUE_AMDON] => 55
)
[1] => Array
(
[YEAR] => 2019
[VALUE_AMDON] => 57
)
[2] => Array
(
[YEAR] => 2020
[VALUE_AMDON] => 59
)
)
And I want to replace with the VALUE_AMDON if value from $priceYear == YEAR
So the output should look like this
$priceYear = Array (
[AZ] => Array
(
[1] => 59
[2] => 59
)
[BY] => Array
(
[0] => 59
[1] => 59
)
[CX] => Array
(
[1] => 59
[2] => 59
[3] => 59
)
[DW] => Array
(
[106] => 57
[107] => 57
[108] => 57
)
)
I'm doing it like this
function replace($var){
global $array;
for ($u=0; $u <sizeof($array) ; $u++) {
if ($var == $array[$u]['YEAR']){
return $array[$u]['VALUE_AMDON'];
}else{
return $var;
}
}
}
foreach ($priceYear as $key => $value) {
$priceYear[$key] = array_map('replace', $value);
}
But unfortunately it is not working, it is returning the initial array
If someone can help me, looks like the error is very dumb but i'm not seeing it :c
You can also do it with array functions like array_column and array_search check below:
$array_year = array_column($array, "YEAR");
foreach($priceYear as $key => $val){
foreach($val as $innerkey => $innerval){
// Below If year exist in $array_year function return key of $array_year else return false
$isExistKey = array_search($innerval, $array_year);
if($isExistKey !== FALSE){
$priceYear[ $key ][ $innerkey ] = $array[ $isExistKey ]["VALUE_AMDON"];
}
}
}
echo "<pre>";
print_r($priceYear);
Check the output here: https://paiza.io/projects/gUNihGow6-CWO0eqWpEtxg?language=php
Because there is no direct link between the keys of the arrays, the easiest way to do this is to use nested loops.
You just need to loop through your $priceYear array and check each of the "year" value acainst the YEAR value in $array. If they match, you can replace just that value in your $priceYear array.
The code below is commented to tell you what each line is doing:
// 1. loop through the nested arrays in $priceYear
foreach ($priceYear as $key => $price_years_array) {
foreach ($price_years_array as $index => $price_years_value) {
// 2. Create a variable to store the new value for the year in this $priceYear array,
// initialised to 0 (your specified default)
$new_year = 0;
// 3. check each year in your $array
foreach ($array as $replacement_values){
// 4. if $replacement_values has a YEAR and VALUE_AMDON...
// and $price_years_value matches the value in YEAR...
if( $replacement_values['YEAR'] && $replacement_values['VALUE_AMDON']
&& $replacement_values['YEAR'] == $price_years_value){
// 5. store this in our $new_year variable
$new_year = $replacement_values['VALUE_AMDON'];
}
}
// 6. after checking all years in $array, it we found a match it will be in $new_year
// otherwise it will still be 0.
// Now simple set this value - we can access this directly using $key and $index
$priceYear[$key][$index] = $new_year;
}
}
var_dump($priceYear);
Sample Data using years that don't exist:
$priceYear = array(
'AZ' => array( 1 => 2021, 2 => 2020), // <-- 2021 doesn't exist in $array
'BY' => array( 0 => 2020, 1 => 2016), // <-- 2016 doesn't exist in $array
'CX' => array(1 => 2020, 2 => 2020, 3 => 2020),
'DW' => array(106 => 2019, 107 => 2019, 108 => 2019)
);
$array = array(
array('YEAR' => 2018, 'VALUE_AMDON' => 55),
array('YEAR' => 2019, 'VALUE_AMDON' => 57),
array('YEAR' => 2020, 'VALUE_AMDON' => 59)
);
Output:
Array
(
[AZ] => Array
(
[1] => 0 // <-- value is 0 because year didn't exist in $array
[2] => 59
)
[BY] => Array
(
[0] => 59
[1] => 0 // <-- value is 0 because year didn't exist in $array
)
[CX] => Array
(
[1] => 59
[2] => 59
[3] => 59
)
[DW] => Array
(
[106] => 57
[107] => 57
[108] => 57
)
)

PHP usort 2 dimensional array not working (sort by integer)

I have this array: $attachments = array();
Which is populated like this:
if (have_rows('attachments_items')):
while ( have_rows('attachments_items') ) : the_row();
$attachment_id = get_sub_field('fileattachment',false);
$year = get_sub_field('year',false);
if(is_null($year) || $year == 0){
$year=2018;
}
$attachments[$i]['year'] = (int)$year;
$attachments[$i]['id'] = $attachment_id;
$i++;
endwhile;
endif;
I want to sort it by year so I tried that:
usort($attachments,function($first,$second){
return $first->year < $second->year;
});
But its not working:
Before
unsorted:Array (
[0] => Array ( [year] => 2018 [id] => 14689 )
1
=> Array ( [year] => 2017 [id] => 14690 )
2 => Array ( [year] => 2018 [id] => 14688 )
[3] => Array ( [year] => 2018 [id] => 14687 ) .....)
After
sorted:Array (
[0] => Array ( [year] => 2018 [id] => 14689 )
1
=> Array ( [year] => 2018 [id] => 16323 )
2 => Array ( [year] => 2018 [id] => 21545 )
[3] => Array ( [year] => 2017 [id] => 14690 )
[4] => Array ( [year] => 2018 [id] => 12711 )
.....)
I think you are trying to sort arrays but you are using the fields as object properties $first->year.
Try using
usort($attachments, function ($first, $second) {
return $first["year"] < $second["year"];
});
print_r($attachments);
Demo

Fill missing array elements with zero values Codeigniter

I am fetching data from database which have dates that need to be sent to the view to create a chart. Some months might not have transactions which I need them to be autofilled with 0.
Model
function get_chart_data()
{
$this->db->order_by('month','asc');
$this->db->select('COUNT(*) as no_payments, SUM(amount) as total_payment_amount, YEAR(`date_paid`) AS year, MONTH(`date_paid`) AS month');
$this->db->group_by(array("year", "month"));
$this->db->where('tbl_payments.payment_type', "PAYMENT");
return $this->db->get('tbl_payments');
}
When I print_r in my controller the data is
Array ( [0] => stdClass Object ( [no_payments] => 1 [total_payment_amount] => 450 [year] => 2016 [month] => 1 ) [1] => stdClass Object ( [no_payments] => 5 [total_payment_amount] => 1162 [year] => 2016 [month] => 5 ) [2] => stdClass Object ( [no_payments] => 2 [total_payment_amount] => 1700 [year] => 2016 [month] => 6 ) )
How can I fill in the missing months and data with zero i.e the data to be
Array ( [0] => stdClass Object ( [no_payments] => 1 [total_payment_amount] => 450 [year] => 2016 [month] => 1 ) [1] => stdClass Object ( [no_payments] => 0 [total_payment_amount] => 0 [year] => 2016 [month] => 2 ) [2] => stdClass Object ( [no_payments] => 0 [total_payment_amount] => 0 [year] => 2016 [month] => 3 ) )
You could add them manually:
$months = array();
$query = $this->db->get('tbl_payments')->result();
foreach($query as $q)
{
$months[] = $q->month;
}
for($i = 1; $i <= 12; $i++)
{
if(!in_array($i, $months))
{
$new_data = new stdClass();
$new_data->no_payments = 0;
$new_data->total_payment_amount = 0;
$new_data->year = 2016;
$new_data->month = $i;
$query[] = $new_data;
}
}
That is asuming you will only need the filling months for current year. If you query other years, you may add that to the logic and include it in another loop.

Find duplicate values in a multidimensional array and create new multidimensional array that contains no dupes

I have the following array taken from a database:
Array
(
[0] => Array
(
[facility_name] => AFC Clayton Juniors
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 20
[end_time] => 21
)
[1] => Array
(
[facility_name] => AFC Clayton Juniors
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 22
[end_time] => 23
)
[2] => Array
(
[facility_name] => Chorlton Runners
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 10
[end_time] => 11
)
[3] => Array
(
[facility_name] => Chorlton Runners
[day] => 15
[month] => Apr
[year] => 2016
[start_time] => 19
[end_time] => 20
)
)
And I need it to be nested as follows::
Array
(
[0] => Array
(
[facility_name] => AFC Clayton Juniors
[dates] => Array
(
[date1] => Array
(
[date] => 15 Apr 2016
[timeslots] => Array
(
[timeslot1] => Array
(
[start_time] => 20
[end_time] => 21
)
[timeslot2] => Array
(
[start_time] => 22
[end_time] => 23
)
)
[date2] => 16 Apr 2016 //etc
)
)
[1] => Array
(
[facility_name] = Chorlton Runners
[dates] => Array //etc
)
)
To elaborate: I need to have NO duplicate names in my array, and the dates that exist for the same name to be entered as new keys to the dates array that match the same name, and the same thing for time slots. How can I do this?
For this solution let's say the array taken from the databse is named $facilities. The code would be:
$noDupes = array();
foreach ($facilities as $fac) {
$facilityIndex = -1; // The index of the facility name, -1 indicates it wasn't found.
$dateIndex = ''; // The index of the date string, an empty string indicates it wasn't found.
$timeslotIndex = ''; // The index of the timeslot, an empty string indicates it wasn't found.
$facDate = "{$fac['day']} {$fac['month']} {$fac['year']}"; // The date string (dd mmm aaaa)
foreach ($noDupes as $f => $facility) {
if ($fac['facility_name'] == $facility['facility_name']) {
// If the facility name was found we take the corresponding index (0, 1, 2, etc.).
$facilityIndex = $f;
foreach ($facility['dates'] as $d => $date) {
if ($facDate == $date['date']) {
// If the date string was found we take the corresponding index (date1, date2, date3, etc.).
$dateIndex = $d;
foreach ($date['timeslots'] as $t => $timeslot) {
if ($fac['start_time'] == $timeslot['start_time'] && $fac['end_time'] == $timeslot['end_time']) {
// If the timeslot was found we take the corresponding index (timeslot1, timeslot2, timeslot3, etc.).
$timeslotIndex = $t;
break; // end timeslot loop
}
}
break; // end date loop
}
}
break; // end facility loop
}
}
if ($facilityIndex == -1) {
// Take the new index for the date and timeslot if-statements
$facilityIndex = count($noDupes);
$noDupes[] = array(
'facility_name' => $fac['facility_name'],
'dates' => array()
);
}
if ($dateIndex == '') {
// Calculate the new index for the date (date1, date2, etc.)
$dateNum = count($noDupes[$facilityIndex]['dates']) + 1;
$dateIndex = "date{$dateNum}";
$noDupes[$facilityIndex]['dates'][$dateIndex] = array(
'date' => $facDate,
'timeslots' => array()
);
}
if ($timeslotIndex == '') {
// Calculate the new index for the timeslot (timeslot1, timeslot2, etc.)
$timeslotNum = count($noDupes[$facilityIndex]['dates'][$dateIndex]['timeslots']) + 1;
$timeslotIndex = "timeslot{$timeslotNum}";
$noDupes[$facilityIndex]['dates'][$dateIndex]['timeslots'][$timeslotIndex] = array(
'start_time' => $fac['start_time'],
'end_time' => $fac['end_time']
);
}
}
Using JSON array will make your task very easy, and is supported in PHP

Categories