Toon posts:

[WordPress] Menu array parents en childs

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Mijn vraag
Ik wil graag mijn hoofdmenu in de JSON API op kunnen halen, maar ik loop tegen een probleem aan om de array met alle menu items op de juiste manier op te bouwen om de child menu items netjes te nesten.

De opbouw die ik graag zou willen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
{
  "nav": {
    "23": {
      "ID": 23,
      "url": "http://localhost/",
      "title": "Home",
      "target": "",
      "classes": [
        ""
      ],
      "subitems": {
        "24": {
          "ID": 24,
          "url": "http://localhost/voorbeeld-pagina/",
          "title": "Voorbeeld pagina TEST",
          "target": "",
          "classes": [
            "test-class"
          ],
          "parent": "23",
          "subitems": {
            "49": {
              "ID": 49,
              "url": "http://localhost/voorbeeld-pagina/",
              "title": "Voorbeeld pagina",
              "target": "",
              "classes": [
                "test1",
                "test2"
              ],
              "parent": "24",
              "subitems": {
                "50": {
                  "ID": 50,
                  "url": "http://localhost/",
                  "title": "Home",
                  "target": "",
                  "classes": [
                    ""
                  ],
                  "parent": "49"
                }
              }
            }
          }
        }
      }
    },
    "48": {
      "ID": 48,
      "url": "http://localhost/test-pagina/",
      "title": "test pagina",
      "target": "",
      "classes": [
        ""
      ]
    }
  }
}


Met de volgende code lukt het me om tot 3 subniveau's te komen, maar dat kan natuurlijk netter en zonder herhalen van code. Het nesten wil ik automatisch laten verlopen, omdat je anders zo oneindig door kunt schrijven en het op deze manier om een soort van "hard coded" nesting gaat. Kan iemand me uitleggen hoe ik dit op een nette manier, met snelle performance, voor elkaar kan krijgen?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Menu items
        $menu_locations = get_nav_menu_locations();

        if ( isset( $menu_locations['header-menu'] ) ) {
            $get_menu_items = wp_get_nav_menu_items( $menu_locations['header-menu'] );
            $root_parent_item = null;
            $subitem_parent = false;

            foreach ( $get_menu_items as $item ) {
                $item_id = $item->ID;
                $parent  = $item->menu_item_parent;

                if ( ! $parent ) {
                    $output['nav'][ $item_id ] = array(
                        'ID'      => $item_id,
                        'url'     => $item->url,
                        'title'   => $item->title,
                        'target'  => $item->target,
                        'classes' => $item->classes,
                    );

                    $root_parent_item = $item_id;
                } else {
                    if( empty ($subitem_parent) ) {
                        $output['nav'][ $root_parent_item ]['subitems'][ $item_id ] = array(
                            'ID'      => $item_id,
                            'url'     => $item->url,
                            'title'   => $item->title,
                            'target'  => $item->target,
                            'classes' => $item->classes,
                            'parent'  => $parent,
                        );

                        $subitem_parent = $item_id;
                    } else {
                        $output['nav'][ $root_parent_item ]['subitems'][ $subitem_parent ]['subitems'][ $item_id ] = array(
                            'ID'      => $item_id,
                            'url'     => $item->url,
                            'title'   => $item->title,
                            'target'  => $item->target,
                            'classes' => $item->classes,
                            'parent'  => $parent,
                        );
                    }
                }
            }
        }


Met daarbij de output (bij item met ID 50 gaat het mis, dit is een child van item met ID 49, en zo dus in de "subitems" van 49 moeten komen):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{
  "nav": {
    "23": {
      "ID": 23,
      "url": "http://localhost/",
      "title": "Home",
      "target": "",
      "classes": [
        ""
      ],
      "subitems": {
        "24": {
          "ID": 24,
          "url": "http://localhost/voorbeeld-pagina/",
          "title": "Voorbeeld pagina TEST TITLE",
          "target": "",
          "classes": [
            "test-classje"
          ],
          "parent": "23",
          "subitems": {
            "49": {
              "ID": 49,
              "url": "http://localhost/voorbeeld-pagina/",
              "title": "Voorbeeld pagina",
              "target": "",
              "classes": [
                "test1",
                "test2"
              ],
              "parent": "24"
            },
            "50": {
              "ID": 50,
              "url": "http://localhost/",
              "title": "Home",
              "target": "",
              "classes": [
                ""
              ],
              "parent": "49"
            }
          }
        }
      }
    },
    "48": {
      "ID": 48,
      "url": "http://localhost/test-pagina/",
      "title": "test pagina",
      "target": "",
      "classes": [
        ""
      ]
    }
  }
}

De PHP code die ik nu heb doet nu het volgende:
Menu locaties ophalen -> ID van het menu dat nu op de header-menu locatie is ingesteld
Als er een menu is ingesteld: ophalen menu items
Dan komt er een array terug met deze opbouw (versimpelde weergave):

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
array(5) {
    [0]=>
  object(WP_Post)#5594 (37) {
  ["ID"]=>
    int(23)
    ["menu_item_parent"]=>
    string(1) "0"
    ["url"]=>
    string(17) "http://localhost/"
    ["title"]=>
    string(4) "Home"
    ["classes"]=>
    array(1) {
        [0]=>
      string(0) ""
    ["menu_item_parent"]=>
     string(1) "0"
    }
array(5) {
    [0]=>
  object(WP_Post)#5594 (37) {
  ["ID"]=>
    int(25)
    ["menu_item_parent"]=>
    string(1) "0"
    ["url"]=>
    string(17) "http://localhost/"
    ["title"]=>
    string(4) "Home"
    ["classes"]=>
    array(1) {
        [0]=>
      string(0) ""
    ["menu_item_parent"]=>
     string(2) "23"
    }
  }


Daarna loopt de code met een foreach door alle items heen, en maakt daarbij onderscheid tussen absolute "root" items en items die een child zijn.

In dit voorbeeld is het 2e item met ID 25 een child van het eerste item met ID 23. Alle onnodige data heb ik daar even tussenuit gehaald. Maar dat gaat zo "oneindig" verder, het volgende item met bijvoorbeeld ID 28 kan weer een child zijn van ID 25, enzovoort. En juist daar gaat het mis, bij het nesten van childs onder andere childs, etc.
Relevante software en hardware die ik gebruik
WordPress 5.3.2

Wat ik al gevonden of geprobeerd heb
Dingen zoals array_walk (_recursive), veel gezocht. Maar geen van de topics hier of op bijvoorbeeld Stackoverflow kan me geven wat ik zoek. En daarnaast wil ik ook graag leren begrijpen wat ik het beste kan doen met dit probleem :)

Beste antwoord (via Verwijderd op 01-04-2020 11:34)


  • regtur2
  • Registratie: December 2008
  • Laatst online: 08:57
Lijkt mij dat je opzoek bent naar een recursive functie.

Alle reacties


Acties:
  • +1 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
Heb je al een reference array geprobeerd?

Maak je niet druk, dat doet de compressor maar


Acties:
  • Beste antwoord
  • +2 Henk 'm!

  • regtur2
  • Registratie: December 2008
  • Laatst online: 08:57
Lijkt mij dat je opzoek bent naar een recursive functie.

Acties:
  • +2 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Just so we're clear... wat versta jij onder een "reference array" :? Want dat is niet echt "een ding" zeg maar...

[ Voor 10% gewijzigd door RobIII op 31-03-2020 22:19 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
regtur2 schreef op dinsdag 31 maart 2020 @ 22:14:
Lijkt mij dat je opzoek bent naar een recursive functie.
Hier zal ik eens verder onderzoek naar doen, misschien is er in die hoekiets wat ik kan gebruiken. Ik kom er nog op terug.

Dank voor de reacties :D

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dat was inderdaad een goede zet in de goede richting.

Met deze code en wat lichte aanpassingen daaraan doet het precies wat ik nodig had:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function buildTree( array &$elements, $parentId = 0 )
{
    $branch = array();
    foreach ( $elements as &$element )
    {
        if ( $element->menu_item_parent == $parentId )
        {
            $children = buildTree( $elements, $element->ID );
            if ( $children )
                $element->subitems = $children;

            $branch[$element->ID] = $element;
            unset( $element );
        }
    }
    return $branch;
}


(gevonden op StackExchange)

Nogmaals dank voor de input!

Acties:
  • 0 Henk 'm!

  • DJMaze
  • Registratie: Juni 2002
  • Niet online
RobIII schreef op dinsdag 31 maart 2020 @ 22:18:
Just so we're clear... wat versta jij onder een "reference array" :? Want dat is niet echt "een ding" zeg maar...
code:
1
2
3
4
$menu_items = array();
$menu_items_reference = array();

$menu_items_reference[$item->id] = &$menu_items[$iets]; // reference pointer

Hierbij heb je de gewone array $menu_items die je omzet in JSON.
En een $menu_items_reference.

De $menu_items_reference is een single level array met alle [$item->id] en dankzij de pointer maakt het niet uit in welk (sub)level het item in de $menu_items array heeft.

Maak je niet druk, dat doet de compressor maar

Pagina: 1