私は私のコードの一部で少し苦労してる...私は私のメニューレイアウトの配列を持っている:PHP再帰的なメニュー多次元配列ジェネレータ
$navigationMenu = [
SECTION_OVERVIEW => [
'hide' => TRUE,
'id' => 'overview_button',
'order' => 0,
'content/overview.php' => [
SECTION_CABINET => [
'hide' => TRUE,
'id' => 'cabinet_button',
'content/cabinet.php' => [
SECTION_AMP_PSU => [
'hide' => TRUE,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => [
SECTION_AMPS_OFF => [
'hide' => false,
'id' => 'amps_off_button',
'ampNoIndicator' => TRUE,
'class' => 'red',
'order' => 4,
],
SECTION_AMPS_ALARMS => [
'id' => 'amps_alarms',
'ampNoIndicator' => TRUE,
'order' => 5,
'content/amp_alarms.php' => NULL
]
]
],
'POOP' => [
'hide' => false,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => NULL
]
]
]
]
],
SECTION_SYSCONFIG => [
'id' => 'sysConfig',
'order' => 1,
'content/system_configuration.php' => NULL,
],
SECTION_SYS => [
'id' => 'system',
'order' => 2,
'content/system.php' => NULL,
],
BACK_BUTTON => [
'id' => 'backBtn',
'order' => 100,
'prev' => NULL,
],
RESCAN_BUTTON => [
'id' => 'rescan',
'order' => 101,
]
];
をそして私は、メニューを生成するクラスを持っています。
class Navigation {
private $doc;
private $xpath;
private $rootNode;
/**
* Initialize navigation.
*/
public function __construct() {
global $navigationMenu;
$menu = $navigationMenu;
$this->doc = new DOMDocument();
$this->doc->appendChild($this->buildMenu($menu));
$this->xpath = new DOMXpath($this->doc);
}
/**
* Build Menu
* @param $menu array see $menu array at the begining of the class
* @param $depth int maintain a depth count for nested UL menu
* @param $nestingUL bool false (default): does not output menu in a nested UL config
* true: nested UL config
*
* @return DOMElement function returns DOM element of UL
*/
private function buildMenu($menu, $depth = 0, $nestingUL = false) {
$ulNode = $this->doc->createElement('ul');
if (!$depth) {
$ulNode->setAttribute('id', 'primary-nav');
$this->rootNode = $ulNode;
}
$this->appendtoNode($menu, $depth, $nestingUL, $ulNode);
return $ulNode;
}
/**
* Append menu items to a node (either UL or LI)
*
* @param $menu array array of menu items list
* @param $depth array depth count for nested UL menu
* @param $nestingUL bool false: no nesting UL; true: nesting UL
* @param $node DOMElement passing node variable
* @param $showElementOverride bool override skipping hidden elements
*
*/
private function appendtoNode($menu, $depth, $nestingUL, $node, $showElementOverride = false) {
foreach ($menu as $itemText => $item) {
if ((empty($item['hide']) || !($item['hide']) || $showElementOverride)) {
$node->appendChild($this->buildMenuItem($itemText, $item, $depth, $nestingUL));
}
else if (array_key_exists('hide', $item) && $item['hide']) {
$newArr = $this->hiddenArraySkipNext($menu);
$this->appendtoNode($newArr, $depth, $nestingUL, $node, $showElementOverride);
}
}
return;
}
/**
* Build menu item.
*
* @param $itemText string (button/menu label)
* @param $item array (button modifiers array)
* @param $depth int (maintaining depth count (only for creating a nested UL))
* @param $nesting bool (true if nesting is required; false if no nesting)
*/
private function buildMenuItem($itemText, $item, $depth, $nesting) {
$id = '';
$spanclassAttr = array('navButton-color');
$order = '';
$url = '';
$ampNo = '';
$childMenu = false;
// prepare node structure
$liNode = $this->doc->createElement('li');
$spanNode = $this->doc->createElement('span');
$glareNode = $this->doc->createElement('span'); // spare span tag used to carry the glare class attribute
$pNode = $this->doc->createElement('p');
// initialize node attributes
$liNode->setAttribute('class', 'navButton');
$glareNode->setAttribute('class', 'glare'); // spare span tag with "glare" class attribute
// iterate item properties
foreach ($item as $key => $value) {
switch ($key) {
case 'hide':
break;
case 'id':
$id = $value;
break;
case 'ampNoIndicator':
$ampNo = $value;
break;
case 'class':
$spanclassAttr[] = $value;
break;
case 'order':
$order = $value;
break;
default:
$url = $key;
$childMenu = $value;
}
}
// map iterated items to nodes
$liNode->setAttribute('id', $id);
if ($spanclassAttr) {
$spanNode->setAttribute('class', implode(' ', $spanclassAttr));
}
$pNode->nodeValue = $itemText;
$spanNode->appendChild($pNode);
$liNode->appendChild($spanNode);
$liNode->appendChild($glareNode);
if (is_array($childMenu) && $nesting) {
$liNode->appendChild($this->buildMenu($childMenu, $depth + 1, $nesting));
}
else if (is_array($childMenu) && !$nesting) {
$this->appendtoNode($childMenu, $depth, $nesting, $liNode);
}
return $liNode;
}
/**
* Iterating menu array
*
* @param $item menu array
* @return array | bool return the nested array, else return false
*/
private function hiddenArraySkipNext($arr) {
$output = $arr;
foreach ($arr as $tempArr) {
if (array_key_exists('hide', $tempArr) && $tempArr['hide']) {
foreach ($tempArr as $key => $value) {
if (is_array($value)) {
$output = $value;
$this->hiddenArraySkipNext($output);
}
}
}
else if (!array_key_exists('hide', $tempArr) || (array_key_exists('hide', $tempArr) && !$tempArr['hide'])) {
return $output;
}
}
return $output;
}
/**
* Get menu.
*/
public function getMenu() {
return $this->doc->saveHTML();
}
}
だから、クラスの目的は、$ navigationMenuのネストされたまたは非ネストされたULのいずれかを生成することができることです(私はbuildMenu、appendtoNodeて持って$ nestingUL/$ネスティングパラメータの使用を参照してください等)。私は$ navigationMenu(appendtoNode()関数の$ showElementOverrideを参照してください)の "隠す"キーをオーバーライドする機能も必要です。配列が設定されている場合、メニューは計画通りに表示されます。しかし、メニューを拡張したいと思ったら、私は問題にぶつかります。
この配列構成では、私のSECTION_AMPS_OFFとSECTION_AMPS_ALARMSが2回出力されます。
$navigationMenu = [
SECTION_OVERVIEW => [
'hide' => TRUE,
'id' => 'overview_button',
'order' => 0,
'content/overview.php' => [
SECTION_CABINET => [
'hide' => TRUE,
'id' => 'cabinet_button',
'content/cabinet.php' => [
SECTION_AMP_PSU => [
'hide' => TRUE,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => [
SECTION_AMPS_OFF => [
'hide' => false,
'id' => 'amps_off_button',
'ampNoIndicator' => TRUE,
'class' => 'red',
'order' => 4,
],
SECTION_AMPS_ALARMS => [
'id' => 'amps_alarms',
'ampNoIndicator' => TRUE,
'order' => 5,
'content/amp_alarms.php' => NULL
]
]
],
'POOP' => [
'hide' => true,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => NULL
]
]
]
]
],
SECTION_SYSCONFIG => [
'id' => 'sysConfig',
'order' => 1,
'content/system_configuration.php' => NULL,
],
SECTION_SYS => [
'id' => 'system',
'order' => 2,
'content/system.php' => NULL,
],
BACK_BUTTON => [
'id' => 'backBtn',
'order' => 100,
'prev' => NULL,
],
RESCAN_BUTTON => [
'id' => 'rescan',
'order' => 101,
]
];
メニューを次のように設定すると、許容されるメモリサイズが枯渇してしまうという致命的なエラーが発生します。
$navigationMenu = [
SECTION_OVERVIEW => [
'hide' => TRUE,
'id' => 'overview_button',
'order' => 0,
'content/overview.php' => [
SECTION_CABINET => [
'hide' => TRUE,
'id' => 'cabinet_button',
'content/cabinet.php' => [
SECTION_AMP_PSU => [
'hide' => TRUE,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => [
SECTION_AMPS_OFF => [
'hide' => true,
'id' => 'amps_off_button',
'ampNoIndicator' => TRUE,
'class' => 'red',
'order' => 4,
],
SECTION_AMPS_ALARMS => [
'id' => 'amps_alarms',
'ampNoIndicator' => TRUE,
'order' => 5,
'content/amp_alarms.php' => NULL
]
]
],
'POOP' => [
'hide' => false,
'id' => 'amps_psu_button',
'ampNoIndicator' => TRUE,
'order' => 3,
'content/amp_psu.php' => NULL
]
]
]
]
],
SECTION_SYSCONFIG => [
'id' => 'sysConfig',
'order' => 1,
'content/system_configuration.php' => NULL,
],
SECTION_SYS => [
'id' => 'system',
'order' => 2,
'content/system.php' => NULL,
],
BACK_BUTTON => [
'id' => 'backBtn',
'order' => 100,
'prev' => NULL,
],
RESCAN_BUTTON => [
'id' => 'rescan',
'order' => 101,
]
];
解決策がメモリの制限を拡大していないことは間違いありません。最終的な目標は、配列をループして、$ showElementOverrideがTRUEに設定されていない限り、非表示のナビゲーションメニューボタン(ネストされたULまたはネストされていないUL)を吐き出すことです。親配列が隠されている場合、その子はネストされたULでない限り表示されます。私はhiddenArraySkipNext()関数に取り組もうとしているので、まだこの問題に取り組んでいません。私は過去2〜3日間これに苦しんでいたので、目の新鮮なセットは間違いなく評価されるでしょう!
あなたがメモリ不足に行けば、チャンスはある、あなたの再帰は終了しません。 – Jakumi
ええ、私は多くを考えました。 hiddenArraySkipNext()関数内の私の2番目のforeachループは、その関数が私のnavメニュー配列のSECTION_AMPS_OFFネストされた配列にループするときに強制的に実行されるので、その理由がわかります。 – JayZiggaZeus