Sum objects in array by the key of month

43 views Asked by At

In ModX (which uses xPDO for queries), I have a custom snippet used to build an array with key of 'publishedon' date, and value of a template variable called 'pnl'.

If you're not familiar with ModX, it's a PHP-based CMS, and a template variable is simply a custom field used to store different types of data. In this case, 'pnl' stores an integer.

This is the script:

$output = array();

//the Parent ID of child resources containing 'pnl' template variable 
$ids = $modx->getChildIds(6);

//Query criteria
$criteria = $modx->newQuery('modResource');

$criteria->where(array(
    'id:IN' => $ids,
    'published' => '1',
    'template' => '3'
));

//Sort results by resource 'publishedon' date
$criteria->sortby('publishedon', 'ASC');

//Build array from selected criteria using getCollection
$docs = $modx->getCollection('modResource', $criteria);

//Walk array
foreach ($docs as $doc) {

// Retrieve the publishedon date for each resource
    $date = strtotime($doc->get('publishedon'));
    
// convert UNIX timestamp to pretty date
    $month = date('M d y', $date);
            
// Get template variable value ('pnl') from each resource
    $pnl = $doc->getTVValue('pnl');
    
// Format 'pnl'
    $pnl_formatted = number_format($pnl, 2, '.', ', ');
    
// build array when 'pnl' is not null or zero
    if (!empty($pnl_formatted) && ($pnl_formatted !== '0.00'))  {
        
        $output[$month] = '$'.$pnl_formatted;

    }

}

print_r($output);

In this example, $month is formatted as Month Day Year, and prints as:

Array ( [Oct 17 22] => $-20.25
        [Oct 18 22] => $61.75
        [Oct 19 22] => $-74.50
        [Oct 20 22] => $165.25
        ...
        [Mar 30 23] => $-36.00 )

I need to summarize 'pnl' by month, rather than show each distinct value by publishedon date, for a result like:

Array ( [Oct 22] => $132.25
        ...            
        [Mar 23] => SUM)

I'm not sure how to go about this. I tried formatting $month as Month Year and then making

 $output[$month] += '$'.$pnl_formatted;

but this does not return the correct value.

1

There are 1 answers

0
jspit On

The day from the date string is removed with substr_replace. Is the simplest for this particular case. Before adding, the $ sign must be removed.

$input = [
  "Oct 17 22" => "$-20.25",
  "Oct 18 22" => "$61.75",
  "Oct 19 22" => "$-74.50",
  "Oct 20 22" => "$165.25",
  //...
  "Mar 30 23" => "$-36.00"
];

$result = [];
foreach($input as $date => $price){
  $key = substr_replace($date,"",3,3);  //remove day
  $result[$key] ??= '$0.0';
  $result[$key] = '$'.(substr($result[$key],1) + substr($price,1));
}
var_dump($result);
// array(2) { ["Oct 22"]=> string(7) "$132.25" ["Mar 23"]=> string(4) "$-36" }