Ok
foreach ( $dept_codes as $d ) {
$production_history[$d] = [];
}
This can be replaced with array_fill_keys
$production_history = array_fill_keys($dept_codes, []);
Next up,
foreach ( $dept_codes as $d ) {
//loop through returned db rows
foreach ( get_production_history( $order_id, $pdo ) as $row ) {
if( $row['dept_code'] == $d ) {
This ends up querying your database count($dept_codes) times when you only really need to do so once as far as I can tell. For each $dept_codes loop you're querying the database for all your results, then just filtering them out to only the ones matching the current department. Instead of doing that, just query your database once and process the results according to the department in the current row.
foreach (get_production_history($order_id, $pdo) as $row){
$d = $row['dept_code'];
//set start time
if ( !in_array ( $row[ 'id' ], $production_history[ $d ]) && $row[ 'status_id' ] === 1 ) {
$production_history[$d][ $row['id'] ] = array(
'submit_time' => $row[ 'submit_time' ],
'finish_time' => '',
);
//record id
$last_recorded = $row['id'];
//set finished time
} elseif ( $row[ 'status_id' ] === 3 ) {
$production_history[$d][ $last_recorded ]['finish_time'] = $row[ 'submit_time' ];
}
}
Since your thread was prompted by anonymous functions, why not use them?
//find records without a finish time and unset them
foreach ( $production_history as $dept => $value )
foreach ($value as $k => $v)
if (empty($v['finish_time']))
unset($production_history[$dept][$k]);
//find departments without records and unset them
foreach ( $production_history as $dept => $value )
if (empty($value))
unset($production_history[$dept]);
Could be replaced with a mix of array_filter and array_walk:
array_walk($production_history, function(&$entryList){
$entryList = array_filter($entryList, function($value){
return !empty($value['finish_time']);
});
});
$production_history = array_filter($production_history);
First array_walk loops over the $production_history array like your foreach loop, each value is passed to the function as $entryList (using a reference so we can modify it). Then the function uses array_filter to keep only entries which have a finish_time defined.
//if on first entry for dept print parent
if ( $dept_arr_count == 0 ) {
//generate parent JSON entry
$json[] = array(
'pID' => $dept,
'pName' => get_dept_name( $dept, $pdo ),
'pStart' => '',
'pEnd' => '',
'pClass' => 'ggroupblack',
'pLink' => '',
'pMile' => 0,
'pGroup' => 2,
'pParent' => 0, //need to set this for those that are children
'pOpen' => 1,
'pDepend' => '',
'pCaption' => '',
'pNotes' => '',
);
}
The if statement check here is unnecessary the way your data is setup. $production_history is a unique array of departments. As such, this part of the loop will only run once per department and there's no need to try and track if you're on a new department.
$submit_time = (isset($production_history[$dept][$k]['submit_time'])) ? $production_history[$dept][$k]['submit_time'] : '';
$finish_time = (isset($production_history[$dept][$k]['finish_time'])) ? $production_history[$dept][$k]['finish_time'] : '';
$k is meaningless here. It's value is going to be whatever the last entry of the //find records without a finish time and unset them loop is (or undefined in my replacement version) You're not using these variables anywhere anyway so the entire lines could be removed. I'm not sure what you were attempting with these lines.
$dept .''. $dept_arr_count+1
You might have an operator precedence issue here, it's unclear what your goal is.
Concatenation and addition have the same precedence and are processed left to right so that expression is ($dept.$dept_arr_count)+1. You combine $dept and $dept_arr_count into a single number, then add one to it.
Your spacing however, to me, suggests you intend to add one to $dept_arr_count first, then combine the two numbers. Achieving that requires a set of parenthesis. $dept . ($dept_arr_count+1)
In either case, the empty string is unnecessary and can be removed.
$production_history[$dept][$k]['submit_time']
$production_history[$dept][$k]['finish_time']
$production_history[$dept][$k] is the same as $v, so you can just use $v['submit_time'] and $v['finish_time'] instead.
So, with all those suggestions applied, the new code would look something like this, assuming I didn't goof up somewhere:
//fetch production history data
if( isset ( $action ) && $action == 'get_production_history' ) {
$order_id = $_GET['order_id'];
$production_history = [];
$last_recorded = 0;
$dept_codes = [5,6,7,8,10,11,12];
$production_history = array_fill_keys($dept_codes, []);
//loop through returned db rows
foreach (get_production_history($order_id, $pdo) as $row){
$d = $row['dept_code'];
//set start time
if ( !in_array ( $row[ 'id' ], $production_history[ $d ]) && $row[ 'status_id' ] === 1 ) {
$production_history[$d][ $row['id'] ] = array(
'submit_time' => $row[ 'submit_time' ],
'finish_time' => '',
);
//record id
$last_recorded = $row['id'];
//set finished time
} elseif ( $row[ 'status_id' ] === 3 ) {
$production_history[$d][ $last_recorded ]['finish_time'] = $row[ 'submit_time' ];
}
}
array_walk($production_history, function(&$entryList){
$entryList = array_filter($entryList, function($value){
return !empty($value['finish_time']);
});
});
$production_history = array_filter($production_history);
$json = [];
foreach ( $production_history as $dept => $value ) {
//generate parent JSON entry
$json[] = array(
'pID' => $dept,
'pName' => get_dept_name( $dept, $pdo ),
'pStart' => '',
'pEnd' => '',
'pClass' => 'ggroupblack',
'pLink' => '',
'pMile' => 0,
'pGroup' => 2,
'pParent' => 0, //need to set this for those that are children
'pOpen' => 1,
'pDepend' => '',
'pCaption' => '',
'pNotes' => '',
);
//print children
$dept_arr_count = 0;
foreach ($value as $k => $v) {
$json[] = array(
'pID' => $dept .''. $dept_arr_count+1,
'pName' => '',
'pStart' => $v['submit_time'],
'pEnd' => $v['finish_time'],
'pClass' => 'ggroupblack',
'pLink' => '',
'pMile' => 0,
'pGroup' => 0,
'pParent' => $dept, //need to set this for those that are children
'pOpen' => 1,
'pDepend' => '',
'pCaption' => '',
'pNotes' => '',
);
$dept_arr_count++;
}
}
header('Content-type: text/javascript');
print(json_encode($json, JSON_PRETTY_PRINT));
}