PHP:将API返回对象转换为嵌套数组时遇到结构异常问题
问题:将Salesforce AggregateResult集合转换为以月份名为键的嵌套数组
我从Salesforce API获取了大量AggregateResult类型的SObject对象集合,想把它们转换成以月份名为键的嵌套数组,但目前写的代码生成的结构不符合预期——只有第一个元素用月份名作为键,其余元素都是数字索引,求帮忙解决!
API返回的SObject示例
SObject Object ( [type] => AggregateResult [fields] => stdClass Object ( [expr0] => 12 [Name] => Performance Reviews [Status] => Closed - Approved [expr1] => 30 ) ) SObject Object ( [type] => AggregateResult [fields] => stdClass Object ( [expr0] => 12 [Name] => Performance Reviews [Status] => Closed - Attempted [expr1] => 11 ) ) SObject Object ( [type] => AggregateResult [fields] => stdClass Object ( [expr0] => 12 [Name] => Performance Reviews [Status] => Closed - Contact Declined [expr1] => 13 ) )
目标嵌套数组结构
Array ( [January] => Array ( [0] => Array ( [0] => January [1] => Closed - Approved [2] => 28 ) [1] => Array ( [0] => January [1] => Closed - Approved [2] => 28 ) ) )
当前代码
$query = "SELECT CALENDAR_MONTH(closedDate), recordType.name,status,count(id) FROM case WHERE owner.name ='" . $SFName . "' AND recordType.name IN('DT Case','Performance Reviews') AND closedDate = LAST_N_MONTHS:6 GROUP BY CALENDAR_MONTH(closedDate),recordType.Name,status ORDER BY CALENDAR_MONTH(closedDate)"; $counter = 0; $mprArray = array(); //instantiate our Array $response = $mySforceConnection->query($query); $queryResult = new QueryResult($response); foreach ($queryResult->records as $case) { //turn our query Result into an Obj $sObject = new SObject($case); $recordType = $sObject->Name; $status = $sObject->Status; $month = $sObject->expr0; $count = $sObject->expr1; //this is a filter to weed out a portion of the cases. if ($recordType == "Performance Reviews") { foreach($sObject as $record) { //change the month's number to a month's name $dateObj = DateTime::createFromFormat('!m', $month); $monthName = $dateObj->format('F'); // Create the nested array, it should end up looking like $mprArray[January]. // This is a dynamic name since we're creating an array for each status that exists in performance Reviews $mprArray[$monthName] = array($monthName,$status,$count); // Trying to append our nested array onto the $mprArray so we can work with it later. array_push($mprArray,$mprArray[$monthName]); } } //increase counter $counter = $counter++; } } catch (Exception $e) { print_r($mySforceConnection->getLastRequest()); echo $e->faultstring; }
错误输出结果
Array ( [January] => Array ( [0] => January [1] => Closed - Contact Declined [2] => 15 ) [0] => Array ( [0] => January [1] => Closed - Approved [2] => 28 ) )
解决方案
问题分析
你的代码有两个核心问题:
- 不必要的内层循环:
foreach($sObject as $record)完全多余,$sObject是单个记录对象,循环它会导致重复处理,还容易出错 - 错误的数组赋值方式:
$mprArray[$monthName] = array(...)每次循环都会覆盖掉之前的月份数组,而不是追加新元素array_push($mprArray, $mprArray[$monthName])直接把元素加到根数组层级,导致出现数字索引的条目
修正后的代码
把循环部分改成下面这样:
$query = "SELECT CALENDAR_MONTH(closedDate), recordType.name,status,count(id) FROM case WHERE owner.name ='" . $SFName . "' AND recordType.name IN('DT Case','Performance Reviews') AND closedDate = LAST_N_MONTHS:6 GROUP BY CALENDAR_MONTH(closedDate),recordType.Name,status ORDER BY CALENDAR_MONTH(closedDate)"; $mprArray = array(); // 初始化结果数组 $response = $mySforceConnection->query($query); $queryResult = new QueryResult($response); foreach ($queryResult->records as $case) { $sObject = new SObject($case); $recordType = $sObject->Name; $status = $sObject->Status; $month = $sObject->expr0; $count = $sObject->expr1; // 只处理Performance Reviews类型的记录 if ($recordType == "Performance Reviews") { // 将月份数字转换为完整月份名称(比如12→December) $dateObj = DateTime::createFromFormat('!m', $month); $monthName = $dateObj->format('F'); // 如果当前月份的数组还不存在,先初始化为空数组 if (!isset($mprArray[$monthName])) { $mprArray[$monthName] = []; } // 把当前状态的统计数据追加到对应月份的数组中 $mprArray[$monthName][] = [$monthName, $status, $count]; } }
说明
- 去掉了多余的内层循环和无用的
$counter变量 - 每次处理记录时,先检查月份对应的数组是否存在,不存在则初始化
- 使用
$mprArray[$monthName][] = ...的方式,将新的统计条目追加到对应月份的数组里,而不是覆盖 - 最终生成的结构就是你想要的:月份名为键,每个键对应一个包含所有相关状态数组的嵌套数组
内容的提问来源于stack exchange,提问作者StavenCross
相关产品推荐
相关产品推荐

