Get WordPress Menu Items

User
Get wordpress backend menu item programmatically
Assistant
To **get WordPress admin menu items programmatically**, you can use the global `$menu` and `$submenu` arrays which are populated when the admin menu is being built.

Here’s a simple example you can run inside a custom plugin or within a theme’s `functions.php` to retrieve and inspect all admin menu items:

### ✅ Example: Get All Admin Menu Items

add_action('admin_menu', 'inspect_admin_menu', 999); // Run after all menus are registered

function inspect_admin_menu() {
    global $menu, $submenu;

    echo '<pre>';
    echo "Main Menu:n";
    print_r($menu);     // Main admin menu
    echo "nSubmenu:n";
    print_r($submenu);  // Submenus under each top-level menu
    echo '</pre>';
}

> 🔒 Note: This will output the result in the admin screen, usually before the actual content, which can break layout — use for debugging only.

### 📦 Programmatic Access to Menu Items

Each item in `$menu` is an array like:

[
    5 => [
        0 => 'Posts',
        1 => 'edit_posts',
        2 => 'edit.php',
        3 => '',
        4 => 'menu-top menu-icon-post open-if-no-js menu-top-first',
        5 => 'menu-posts',
        6 => 'dashicons-admin-post'
    ],
    ...
]

The keys mean:
– `[0]`: Menu title
– `[1]`: Capability
– `[2]`: Menu slug (URL path)
– `[6]`: Icon (if exists)

The `$submenu` array is indexed by the top-level menu slug (`edit.php`, `upload.php`, etc.) and contains sub-items.

### ✅ Example: Loop Through All Menu Items

add_action('admin_menu', 'list_all_menu_items', 999);

function list_all_menu_items() {
    global $menu, $submenu;

    echo '<pre>';

    foreach ($menu as $item) {
        $slug = $item[2];
        echo "Top Menu: {$item[0]} ({$slug})n";

        if (isset($submenu[$slug])) {
            foreach ($submenu[$slug] as $subitem) {
                echo "  → Submenu: {$subitem[0]} ({$subitem[2]})n";
            }
        }
    }

    echo '</pre>';
}

### 🧪 For Programmatic Use (No Output)

If

User
Appearnce->Menu
Assistant
If you're trying to programmatically get the **"Appearance > Menus"** admin submenu (specifically the **Menus screen** under the Appearance menu), here’s how you can access it using the `$submenu` array in WordPress:

### ✅ Get "Appearance > Menus" Menu Slug Programmatically

add_action('admin_menu', function () {
    global $submenu;

    // 'themes.php' is the slug for the Appearance menu
    if (isset($submenu['themes.php'])) {
        foreach ($submenu['themes.php'] as $item) {
            if (stripos($item[0], 'menus') !== false) {
                echo '<pre>';
                echo "Label: " . esc_html($item[0]) . "n";
                echo "Capability: " . esc_html($item[1]) . "n";
                echo "Slug: " . esc_html($item[2]) . "n"; // This is the URL part
                echo '</pre>';
            }
        }
    }
}, 999);

### 🔎 Typical Output:

Label: Menus
Capability: edit_theme_options
Slug: nav-menus.php

So the **slug** for `Appearance > Menus` is:

nav-menus.php

You can use this slug to:
– Build URLs: `admin_url('nav-menus.php')`
– Check current page: `if ($_GET['page'] === 'nav-menus.php')`
– Add submenu after it: `add_submenu_page('themes.php', …)`

### 📌 Summary:
– Parent Menu: `themes.php` (Appearance)
– Submenu Title: `Menus`
– Submenu Slug: `nav-menus.php`

Let me know if you want to **add**, **modify**, or **hide** this menu as well.

User
use wp_nav_menu
Assistant
Great! If you're looking to **display a WordPress menu** (like the one created under **Appearance > Menus**) programmatically using `wp_nav_menu()`, here's how you can do it step by step:

## ✅ Basic Usage of `wp_nav_menu()`

<?php
wp_nav_menu([
    'theme_location' => 'primary',
]);
?>

But this requires that the **menu location** `'primary'` is **registered** in your theme.

## 🧩 Step-by-Step Implementation

### 1. ✅ Register the Menu Location (usually in `functions.php`)

function register_my_menus() {
    register_nav_menus([
        'primary' => __('Primary Menu'),
        'footer'  => __('Footer Menu'),
    ]);
}
add_action('after_setup_theme', 'register_my_menus');

### 2. ✅ Assign Menu to a Location

Go to **Appearance > Menus** in the dashboard, and assign a menu to `Primary Menu` (or whichever you registered).

### 3. ✅ Display the Menu in Theme Template

<?php
wp_nav_menu([
    'theme_location' => 'primary',
    'container' => 'nav',             // Wraps the menu in <nav> by default
    'container_class' => 'main-nav',  // Adds a class to <nav>
    'menu_class' => 'menu',           // Adds a class to the <ul>
    'fallback_cb' => false,           // Disable fallback
]);
?>

## 📌 Display Menu by Menu Name or ID (Optional)

If you want to load a menu **directly by its name or ID**, do this:

<?php
wp_nav_menu([
    'menu' => 'Main Menu', // or menu ID
]);
?>

### 🧪 Example HTML Output (Simplified):

<nav class="main-nav">
  <ul class="menu">
    <li class="menu-item"><a href="/">Home</a></li>
    <li class="menu-item"><a href="/about">About</a></li>
    ...
  </ul>
</nav>

Let me know if you want to customize the menu output (like dropdowns, active class, mobile menu support, etc.).

User
$menu=wp_nav_menu([
'menu' => 20, // or menu ID
]);
print_r($menu);
die;
But i want just menu items not html or anything
Assistant
Perfect — you're looking to **get the raw menu items (array)** instead of rendered HTML.

The `wp_nav_menu()` function **returns HTML**, not the raw data. To get **just the menu items**, you should use the lower-level function: `wp_get_nav_menu_items()`.

## ✅ Use `wp_get_nav_menu_items()` for Raw Menu Data

$menu_items = wp_get_nav_menu_items(20); // Use menu ID or slug

echo '<pre>';
print_r($menu_items); // This will show all menu item objects
echo '</pre>';
die;

### 📌 Output Format

Each item is a `WP_Post` object with properties like:

[0] => WP_Post Object (
    [ID] => 45
    [title] => Home
    [menu_order] => 1
    [post_name] => home
    [url] => https://example.com/
    [menu_item_parent] => 0
    [type] => custom
    [object] => custom
    [object_id] => 0
    [target] => 
    [classes] => Array ( [0] => )
    ...
)

## 🧠 If You Want Just Titles and URLs

$menu_items = wp_get_nav_menu_items(20);
$menu_data = [];

foreach ($menu_items as $item) {
    $menu_data[] = [
        'title' => $item->title,
        'url'   => $item->url,
        'parent_id' => $item->menu_item_parent,
    ];
}

echo '<pre>';
print_r($menu_data);
echo '</pre>';

Let me know if you want to structure this as a nested tree (parent-child relationship).

User
its working in bakcend good but in frontn it shows last arrayu item
Array
(
[0] => Array
(
[title] => Gidsen
[url] => https://professor.nl/?cat=1126
[parent_id] => 0
[catid] => 1126
)

)

Assistant
Thanks — based on your response, it looks like:

– Your code to fetch menu items works in **backend (admin)**.
– But in **frontend**, it only returns **one item (the last one)** in the array.

This typically happens due to **caching**, **variable overwriting**, or incorrect scope when building arrays in a loop.

Let me walk you through a clean, correct way to do it.

## ✅ Correct Way to Fetch All Menu Items (Frontend Safe)

$menu_items = wp_get_nav_menu_items(20); // Replace with menu ID or slug

$menu_data = [];

if ($menu_items) {
    foreach ($menu_items as $item) {
        // Example: extracting custom category ID from the URL if needed
        $cat_id = 0;
        if (preg_match('/cat=([0-9]+)/', $item->url, $matches)) {
            $cat_id = $matches[1];
        }

        $menu_data[] = [
            'title'     => $item->title,
            'url'       => $item->url,
            'parent_id' => $item->menu_item_parent,
            'catid'     => $cat_id,
        ];
    }
}

echo '<pre>';
print_r($menu_data);
echo '</pre>';

## ⚠️ Common Issues That Can Cause Only One Item

1. **Overwriting the array in the loop** instead of appending:

$menu_data = [...]; // overwrites each time ❌

Use `[] = …` to append instead ✅

2. **Code inside conditional scope (like `if`, `foreach`)** but outside viewable template

3. **Conflicts with filters/hooks or global scope misuse**

## ✅ Quick Debug Checklist

– Confirm `$menu_items` contains more than one item by doing:

var_dump(count($menu_items));

– Make sure `foreach` is **not overwritten** by assigning instead of appending
– Try `wp_get_nav_menu_items('main-menu-slug')` instead of ID to rule out mismatches

If you can share the exact code used on the frontend, I can pinpoint it precisely. Want me to show how to convert this into a JSON API as well?

User
we have
$categoriesallow=[1252,9,17,1240,1068,35,37,38,1177,1234,1229,40,785,1176,757,1160,1052];
$parent_cats = get_terms([
'taxonomy' => 'product_cat',
'parent' => 0,
'hide_empty' => true,
'orderby' => 'name',
'order' => 'ASC',
'includes'=>$categoriesallow
]);
this order categories array
but I want category will show in order of categoriesallow
Assistant
Great — you're retrieving WooCommerce **parent categories**, and want them to appear in the **exact order** of your `$categoriesallow` array. But `get_terms()` doesn't return them in that order, even if you pass `'include' => $categoriesallow`.

Let's fix it!

## ✅ Step-by-Step Fix

### 1. Correct `get_terms()` parameters:

There is **no `includes`** parameter. It should be `'include'` (singular).

$categoriesallow = [1252,9,17,1240,1068,35,37,38,1177,1234,1229,40,785,1176,757,1160,1052];

$parent_cats = get_terms([
    'taxonomy' => 'product_cat',
    'parent' => 0,
    'hide_empty' => true,
    'include' => $categoriesallow,
    'orderby' => 'include', // respect the order of $categoriesallow
]);

### 2. ✅ Bonus: Force Custom Sorting (if needed)

Sometimes `'orderby' => 'include'` doesn't work consistently. Here's a manual way to sort terms by `$categoriesallow` order:

$categoriesallow = [1252,9,17,1240,1068,35,37,38,1177,1234,1229,40,785,1176,757,1160,1052];

$terms = get_terms([
    'taxonomy' => 'product_cat',
    'include' => $categoriesallow,
    'hide_empty' => true,
]);

// Reorder to match $categoriesallow
$ordered_terms = [];
$terms_by_id = [];

foreach ($terms as $term) {
    $terms_by_id[$term->term_id] = $term;
}

foreach ($categoriesallow as $id) {
    if (isset($terms_by_id[$id])) {
        $ordered_terms[] = $terms_by_id[$id];
    }
}

## ✅ Output

Now `$ordered_terms` contains the category terms in the **exact order** defined in `$categoriesallow`.

Use it like:

foreach ($ordered_terms as $cat) {
    echo $cat->name . '<br>';
}

Let me know if you want to include subcategories or build a nested category tree from this.

Leave a Comment

Your email address will not be published. Required fields are marked *