Reputation: 6165
I have a flat resultset, that looks like this in JSON:
[{
"LineItemNo": "1",
"SolNo": "SPE8E7-15-T-1379",
"St": "O",
"PartNo": "F13DBX\/SPX35\/4P",
"UnitPrice": "1.890"
}, {
"LineItemNo": "1",
"SolNo": "SPE8E7-15-T-1379",
"St": "O",
"PartNo": "CF13DD\/E\/835",
"UnitPrice": "1.920"
}, {
"LineItemNo": "1",
"SolNo": "SPE8E7-15-T-1379",
"St": "O",
"PartNo": "QT13\/35-4",
"UnitPrice": "1.770"
}, {
"LineItemNo": "2",
"SolNo": "SPE8E7-15-T-4309",
"St": "O",
"PartNo": "F13DBX\/SPX35\/4P",
"UnitPrice": "1.890"
}, {
"LineItemNo": "2",
"SolNo": "SPE8E7-15-T-4309",
"St": "O",
"PartNo": "CF13DD\/E\/835",
"UnitPrice": "1.920"
}, {
"LineItemNo": "2",
"SolNo": "SPE8E7-15-T-4309",
"St": "O",
"PartNo": "QT13\/35-4",
"UnitPrice": "1.770"
}]
I want to change it into this:
{
"data": [{
"LineItemNo": "1",
"SolNo": "SPE8E7-15-T-1379",
"St": "O",
"Parts": [{
"PartNo": "F13DBX\/SPX35\/4P",
"UnitPrice": "1.890"
}, {
"PartNo": "CF13DD\/E\/835",
"UnitPrice": "1.920"
}, {
"PartNo": "QT13\/35-4",
"UnitPrice": "1.770"
}]
}, {
"LineItemNo": "2",
"SolNo": "SPE8E7-15-T-4309",
"St": "O",
"Parts": [{
"PartNo": "F13DBX\/SPX35\/4P",
"UnitPrice": "1.890"
}, {
"PartNo": "CF13DD\/E\/835",
"UnitPrice": "1.920"
}, {
"PartNo": "QT13\/35-4",
"UnitPrice": "1.770"
}]
}]
}
I've tried numerous things, but I haven't been able to find a way to iterate through the source array, create a Parts
array during the process, and then plug values into that array during subsequent iterations. What I'd like to do is iterate the source array, check the $row['LineItemNo']
value, and if it has changed since the last iteration, create a new top-level array object. If it hasn't, then create a new element the Parts
array.
My basic code looks like this (I realize mysql is deprecated in favor of mysqli or PDO, but I'm stuck with it for the time being):
$result = mysql_query($query) or die(mysql_error());
$rs = array();
$rsParts = array();
while($row = mysql_fetch_array($result))
{
if (!isset($ln) || $row['LineItemNo'] != $ln)
{
$ln = $row['LineItemNo'];
$rs[data][] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
$rs[data][parts] = array();
}
array_push($rs[data][parts], array('PartNo' => $row['PartNo'], 'UnitPrice' => $row['UnitPrice']));
}
This is a good start, but it only gives me the parts in the first element, like this:
{
"data": {
"0": {
"LineItemNo": "1",
"SolNo": "SPE8E7-15-T-1379",
"St": "O"
},
"parts": [{
"PartNo": "F13DBX\/SPX35\/4P",
"UnitPrice": "1.890"
}, {
"PartNo": "CF13DD\/E\/835",
"UnitPrice": "1.920"
}, {
"PartNo": "QT13\/35-4",
"UnitPrice": "1.770"
}],
"1": {
"LineItemNo": "2",
"SolNo": "SPE8E7-15-T-4309",
"St": "O"
}
}
}
I'm thinking that you can't re-initialize the array this way. I've tried unsetting it when the LineItemNo changes, but that turns all the Parts
elements into top-level elements. I've tried only initializing the array at the beginning using is_array
, but that puts all of the parts into the first top-level element (there are six parts in the first one and none in the second).
So, what's the right way to do what I'm trying to do?
EDIT: the solution of the problem was to first send the resultset ($result
) through this code:
$array = array();
while($r = mysql_fetch_assoc($result))
{
$array[] = $r;
}
And then use SML's solution from there.
Upvotes: 2
Views: 255
Reputation: 1265
Assuming any given LineItemNo
would always be paired with the same SolNo
and St
, you can pass LineItemNo
of each row to a function to check if the value exists in the sub-arrays of the result array $rs
.
If LineItemNo
doesn't already exist in $rs
, then a new first level sub array of $rs
is created and a 2nd level sub array containing parts info
will also be added as sub_array of 1st level array element parts
.
If LineItemNo
does exist, then just add the parts info
as sub_array of 1st level array element parts
.
Since the top level array ['data'] you wanted in the output, doesn't do anything at this stage.
I strip that from the process and instead $rs
is added to $output['data']
in the final stage to form the output you need.
$rs=array();
$counter=0;
while($r = mysql_fetch_assoc($results)) {
$array[]=$r;
}
foreach ($array as $row) {
$part_info = array('part_no' => $row['PartNo'], 'unit_price' => $row['UnitPrice']);
$temp=searchSub ($rs, $row['LineItemNo']);
if ($temp===false){
$rs[$counter] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
$rs[$counter]['parts'][] = $part_info;
$counter++;
}
else {
$rs[$temp]['parts'][]= $part_info;
}
}
//function for subarray search
function searchSub($arr, $keyword){
foreach($arr as $key=>$value)
{
if (in_array($keyword, $value, true)!=false){
return $key;
}
}
return false;
}
$output['data']=$rs;
print_r($output);
Upvotes: 2
Reputation: 5367
array_push
is the way I'd typically do it. You're code is a bit confusing to read (not very user friendly), but I think you're close - very close...
EDIT: Check out the below. Should work. Change your while
to a foreach
and run it like so:
$rs = [];
foreach(mysql_fetch_array($result) as $key => $row)
{
$rs['data'][$key] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
$part_info = array('part_no' => $row['PartNo'], 'unit_price' => $row['UnitPrice']);
$rs['data'][$key]['parts'] = $part_info;
}
print_r($rs);
Upvotes: 2