[英]Recursive traversal of nested objects and extract some properties
我正在努力應對以下情況:
我有一個 Category 類型的對象,它具有幾個私有屬性,我想通過其可用的 getter 將其提取到單獨的數據結構/數組中: getId() 、 getTitle() 、 getLink() 。 它也將任何嵌套的子類別存儲為屬性,可以通過 getter getSubCats()訪問該屬性,該屬性將返回一個關聯的類別數組,其中相應的 ID 作為鍵。
我需要提取一些屬性並創建一個嵌套數組(用於 json_encode),它符合以下結構:
<ID> => array(
'title' => <title>,
'url' => <url>,
'parent' => <parentID>,
'children' => array(
<ID> => array(
'title' => <title>,
'url' => <url>,
'parent' => <parentID>,
'children' => array(
...
),
<ID> => array(
'title' => <title>,
'url' => <url>,
'parent' => <parentID>,
'children' => array(
...
),
...
)
)
也許這可以通過使用 RecursiveIteratorIterator 來完成? 以下是我的最后兩種方法:
function buildTree_v1(&$oCat, &$aOutput = [], &$oParent = null) {
$actId = $oCat->getId();
$aOutput [$actId]['title'] = $oCat->getTitle();
$aOutput [$actId]['url'] = $oCat->getLink();
$aOutput [$actId]['parent'] = $oCat->getParentCategory()->getId() ?? null;
if ( $oCat->getHasVisibleSubCats() ) {
foreach ( $oCat->getSubCats() as $sId => &$oSubCat ) {
$aOutput [$actId][$sId] = [];
foreach ( $oSubCat as &$oSubChild ) {
buildTree_v1($oCat, $aOutput, $oSubChild);
}
}
}
}
// Try to split - only build the nested object structure as first step
function buildTree_v2(&$oCat) {
$return = [];
if ( $oCat->getHasVisibleSubCats() ) {
foreach ( $oCat->getSubCats() as &$oSubCat) {
if ( $oSubCat->getHasVisibleSubCats() ) {
$return[$oSubCat->getId()] = buildTree_v2($oSubCat);
} else {
$return[] = $oSubCat->getId();
}
}
}
return empty($return) ? null : $return;
}
提前感謝您的任何建議!
//編輯:
輸入結構(相關部分):
class Category {
protected $_aSubCats = array();
protected $_blHasVisibleSubCats;
protected $_aSeoUrls = array();
protected $_oParent = null;
protected $_sId;
protected $_sTitle;
public function getSubCats(): array<Category>;
public function getHasVisibleSubCats(): bool;
public function getLink($iLang = null): string;
public function getParentCategory(): ?Category;
public function getId(): string;
public function getTitle(): string;
}
一個具體的示例輸入對象可能如下所示:
$oInputCat = {Category}
-> $_aSubCats = array(
'316' => {Category},
'23' => {Category},
'262' => {Category}
)
-> $_blHasVisibleSubCats = true
-> $_aSeoUrl = 'https://example.com/Hardware'
-> $_oParent = {Category}
-> $_sId = '5068'
-> $_sTitle = 'Hardware'
/* Entries of $_aSubCats */
// '316' = {Category}
-> $_aSubCats = array()
-> $_blHasVisibleSubCats = false
-> $_aSeoUrl = 'https://example.com/Hardware/3D-Googles'
-> $_oParent = {Category}
-> $_sId = '316'
-> $_sTitle = '3D Googles'
// '23' = {Category}
-> $_aSubCats = array(
'26' => {Category}
)
-> $_blHasVisibleSubCats = true
-> $_aSeoUrl = 'https://example.com/Hardware/CPUs-and-Cooler'
-> $_oParent = {Category}
-> $_sId = '23'
-> $_sTitle = 'CPUs & Cooler'
// '262' = {Category}
-> $_aSubCats = array()
-> $_blHasVisibleSubCats = false
-> $_aSeoUrl = 'https://example.com/Hardware/Sound-Cards'
-> $_oParent = {Category}
-> $_sId = '262'
-> $_sTitle = 'Sound Cards'
// '26' = {Category} <-- example for a 2nd level subcategory
-> $_aSubCats = array()
-> $_blHasVisibleSubCats = false
-> $_aSeoUrl = 'https://example.com/Hardware/CPUs-and-Cooler/Cooler'
-> $_oParent = {Category}
-> $_sId = '26'
-> $_sTitle = 'Cooler'
期望的結果如下所示:
array(
'5068' => array(
'title' => 'Hardware',
'url' => 'https://example.com/Hardware',
'parent' => '12', // not listed - parent of the input category
'children' => array(
'316' => array(
'title' => '3D Googles',
'url' => 'https://example.com/Hardware/3D-Googles',
'parent' => '5068',
'children' => array(),
'23' => array(
'title' => 'CPUs & Cooler',
'url' => 'https://example.com/Hardware/CPUs-and-Cooler',
'parent' => '5068',
'children' => array(
'26' => array(
'title' => 'Cooler',
'url' => 'https://example.com/Hardware/CPUs-and-Cooler/Cooler',
'parent' => '23',
'children' => array(),
),
'262' => array(
'title' => 'Sound Cards',
'url' => 'https://example.com/Hardware/Sound-Cards',
'parent' => '5068',
'children' => array(),
)
)
)
真實的對象樹有任意數量的分支和維度,但我認為這應該足以理解我想要做什么。
如您所見,所需的目標可以描述為“在過濾某些特定屬性的同時將對象轉換為數組”。 我希望這會讓事情更容易理解。
最后,我能夠自己解決這個問題。
僅對於存檔,以下代碼將執行該任務:
/**
* Extracts all relevant properties of the given base category and all of its subcategories recursively
* and assigns this data structure to the given template variable.
*
* @param Category $oCat [mandatory] Target base category
* @param array $aOutput [optional] Extraction storage
* @param ?object $oParent [internal] Latest parent
* @param bool $return [internal] Return indicator
*
* @return array|void Derived category tree structure
*/
function buildTree($oCat, &$aOutput = [], $oParent = null, $return = true) {
// scalar properties
$aOutput[$actId]['id'] = $actId = $oCat->getId();
$aOutput[$actId]['title'] = $oCat->getTitle();
$aOutput[$actId]['url'] = $oCat->getLink();
// parent property (object)
if ( $oParent !== null ) {
$aOutput[$actId]['parent'] = $oParent->getId();
} elseif ( $parent = $oCat->getParentCategory() ) {
$aOutput[$actId]['parent'] = $parent->getId();
} else {
$aOutput[$actId]['parent'] = ':globalroot'
}
// subcats property ([object])
if ( $oCat->getHasVisibleSubCats() ) {
foreach ( $oCat->getSubCats() as $sId => $oSubCat ) {
$aOutput[$actId]['children'][$sId] = [
'id' => $sId,
'title' => $oSubCat->getTitle(),
'url' => $oSubCat->getLink(),
'parent' => $actId,
'children' => null
];
if ( $oSubCat->getHasVisibleSubCats() ) {
foreach ( $oSubCat->getSubCats() as $oSubChild ) {
buildTree($oSubChild, $aOutput[$actId]['children'][$sId]['children'], $oSubCat, false);
}
}
}
} else {
$aOutput[$actId]['children'] = null;
}
if ( $return ) {
return $aOutput;
}
}
用法:
$aTree = buildTree($oBaseCat);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.