我試圖構建一個扁平數組,它保留來自我的CodeIgniter項目中來自視圖的相當棘手的數組的元數據。這個元數據就像一個標識符,深度和父節點。PHP:通過遞歸迭代構建鄰接列表
這些數據來自查詢生成器JavaScript庫,它允許用戶生成將用於業務邏輯的規則。我需要堅持這些數據,而我用來表示這些規則的樹狀特性的模型是一個鄰接表。
下面是我的,它適用於大多數情況,但它很醜,它是由泡泡糖和膠帶製成的,而'大多數'情況並非'全部'情況。在閱讀SPL文檔後,我懷疑RecursiveIteratorIterator可能更適合這個問題。
對不起,我很確定我的方法很糟糕。有什麼建議?
這裏的輸入(例如,地方我寧願不是),樣本圖像示出它在行動太:
stdClass Object
(
[condition] => OR
[rules] => Array
(
[0] => stdClass Object
(
[id] => Any
[field] => Any
[type] => string
[input] => select
[operator] => not equal
[value] => Any
)
[1] => stdClass Object
(
[condition] => AND
[rules] => Array
(
[0] => stdClass Object
(
[id] => Place
[field] => Place
[type] => string
[input] => select
[operator] => equal
[value] => France
)
[1] => stdClass Object
(
[id] => Month
[field] => Month
[type] => string
[input] => select
[operator] => equal
[value] => January
)
)
)
[2] => stdClass Object
(
[condition] => AND
[rules] => Array
(
[0] => stdClass Object
(
[id] => Place
[field] => Place
[type] => string
[input] => select
[operator] => equal
[value] => Rio
)
[1] => stdClass Object
(
[id] => Month
[field] => Month
[type] => string
[input] => select
[operator] => equal
[value] => August
)
)
)
[3] => stdClass Object
(
[condition] => AND
[rules] => Array
(
[0] => stdClass Object
(
[id] => Place
[field] => Place
[type] => string
[input] => select
[operator] => equal
[value] => Liberia
)
[1] => stdClass Object
(
[id] => Month
[field] => Month
[type] => string
[input] => select
[operator] => equal
[value] => July
)
[2] => stdClass Object
(
[condition] => OR
[rules] => Array
(
[0] => stdClass Object
(
[id] => Year
[field] => Year
[type] => string
[input] => select
[operator] => equal
[value] => 2014
)
[1] => stdClass Object
(
[id] => Year
[field] => Year
[type] => string
[input] => select
[operator] => equal
[value] => 2015
)
)
)
)
)
)
)
這裏是持久性所需要的輸出。 (請參閱每個條目最右側的值,瞭解元數據的重要部分)。
Array
(
stdClass Object ([id] => Any [field] => Any [type] => string [input] => select [operator] => not equal [value] => Any [condition] => OR [subgroup] => 0 [parent_subgroup] =>)
stdClass Object ([id] => Place [field] => Place [type] => string [input] => select [operator] => equal [value] => France) [condition] => AND [subgroup] => 1 [parent_subgroup] => 0)
stdClass Object ([id] => Month [field] => Month [type] => string [input] => select [operator] => equal [value] => January [condition] => AND [subgroup] => 1 [parent_subgroup] => 0)
stdClass Object ([id] => Place [field] => Place [type] => string [input] => select [operator] => equal [value] => Rio [condition] => AND [subgroup] => 2 [parent_subgroup] => 0)
stdClass Object ([id] => Month [field] => Month [type] => string [input] => select [operator] => equal [value] => August[condition] => AND [subgroup] => 2 [parent_subgroup] => 0)
stdClass Object ([id] => Place [field] => Place [type] => string [input] => select [operator] => equal [value] => Liberia [condition] => AND [subgroup] => 3 [parent_subgroup] => 0)
stdClass Object ([id] => Month [field] => Month [type] => string [input] => select [operator] => equal [value] => July[condition] => AND [subgroup] => 3 [parent_subgroup] => 0)
stdClass Object ([id] => Year [field] => Year [type] => string [input] => select [operator] => equal [value] => 2014 [condition] => OR [subgroup] => 4 [parent_subgroup] => 3)
stdClass Object ([id] => Year [field] => Year [type] => string [input] => select [operator] => equal [value] => 2015 [condition] => OR [subgroup] => 4 [parent_subgroup] => 3)
)
注意:正確解析此。如果我已經更改了子組2和子組3的順序,則會出現問題,因爲組3的子組具有不同的嵌套級別,並嚴重地混淆了我的遞歸規則(年= 2014或年= 2015)。
這裏是我的代碼:
function deserialize_criteria_group($criteria, $subgroup = null) {
$array = array();
if ($subgroup == null) {
$first_run = true;
$subgroup = 0;
$condition = $criteria->condition;
$criteria = $criteria->rules;
}
foreach ($criteria as $rule) {
if ($rule->rules) {
$subgroup++;
$children = $this->deserialize_criteria_group($rule->rules, $subgroup);
foreach($children as $child) {
if ($child->condition == null) {
$child->condition = $rule->condition;
}
if ($child->parent_subgroup == null) {
$child->parent_subgroup = $first_run ? 0 : $subgroup - 1;
}
array_push($array, $child);
}
} else {
$rule->condition = $condition;
$rule->subgroup = $subgroup;
$rule->parent_subgroup = null;
array_push($array, $rule);
}
}
if ($first_run) {
//Ensure a root node exists, if not stub one out.
$criteria_group = json_decode(json_encode($array), true);
$root_encountered = $criteria_group[0]['subgroup'] > 0 ? false : true;
if (!$root_encountered) {
$root = array( 'subgroup' => 0,
'parent_subgroup' => null,
'condition' => $condition);
array_unshift($criteria_group, $root);
array_unshift($array, $root);
}
//Ensure the ALM is not broken.
$subgroup = 0;
foreach($criteria_group as $c) {
if($c['subgroup'] > $subgroup + 1) {
$msg = "Bad Order. Halting execution.";
print $msg;
log_message('error', $msg);
log_message('debug', 'expected: ' . $subgroup . ' actual: ' . $c['subgroup']);
log_message('debug', print_r($criteria_group, true));
die;
}
$subgroup = $c['subgroup'];
}
}
return $array;
}