it-swarm.xyz

wp_get_nav_menu_items () не работает со слагом

Согласно параметру docs , wp_get_nav_menu_items() 1 принимает

(string) (Required) Menu name, ID, or slug.

Вот как я регистрирую свои меню

register_nav_menus(
    array(
        'primary' => 'Navigation primaire',
        'secondary' => 'Navigation secondaire',
    )
);

Вот как я пытался загрузить один

var_dump( wp_get_nav_menu_items('primary') );             // bool(false)
var_dump( wp_get_nav_menu_items('navigation-primaire') ); // bool(false)
var_dump( wp_get_nav_menu_items('Navigation primaire') ); // bool(false)

var_dump( wp_get_nav_menu_items(51) );                      // array([...]) (correct)

Таким образом, функция вернет меню, только когда я использую идентификатор. Я бы предпочел использовать слаг, так как мой сайт многоязычный, и я не хочу использовать разные идентификаторы в зависимости от языка.

Я делаю что-то не так или это основная ошибка? Я пробовал это на теме TwentySixteen с отключенным многоязычным плагином (Polylang).

6
Brian

Поскольку никто не объяснил, почему эта функция не работает так, как вы думали, я постараюсь объяснить ее подробно, так как попал в ту же ловушку, что и вы.

Это где документы не совсем понятно, что относится к слизню. Большинство людей примет это за кусок зарегистрированного меню, но это не правильно. Это на самом деле кусок термина таксономии nav_menu.

Давайте погрузимся в исходный код, чтобы увидеть, как ядро ​​Wordpress интерпретирует фрагмент меню.

function wp_get_nav_menu_items( $menu, $args = array() ) {
    $menu = wp_get_nav_menu_object( $menu );
....

Первая строка показывает, что она использует функцию wp_get_nav_menu_object () для получения меню. Он передает $menu в качестве первого параметра этой функции. Так как это то, что мы используем для нашего слага, нам нужно погрузиться в источник для wp_get_nav_menu_object().

function wp_get_nav_menu_object( $menu ) {
    $menu_obj = false;

    if ( is_object( $menu ) ) {
            $menu_obj = $menu;
    }

    if ( $menu && ! $menu_obj ) {
            $menu_obj = get_term( $menu, 'nav_menu' );

            if ( ! $menu_obj ) {
                    $menu_obj = get_term_by( 'slug', $menu, 'nav_menu' );
            }

            if ( ! $menu_obj ) {
                    $menu_obj = get_term_by( 'name', $menu, 'nav_menu' );
            }
    }
....

мы видим, что эта функция использует функцию get_term_by для получения $menu_obj. Здесь мы получаем наше меню.

Когда вы создаете меню в админке Wordpress, оно создает новый термин. Условия, есть слизни, основанные на их имени. Так что, если у вас есть название меню "My Awesome Menu", Wordpress сгенерирует слаг с именем "my-awesome-menu". Возможно, вы зарегистрировали меню как "первичное", но это не тот параметр, к которому относятся эти функции. Это на самом деле термин меню слизень.

Итак, чтобы быть ясным, давайте просто скажем, что вы зарегистрировали меню так:

register_nav_menu('primary', 'my primary nav');

primary это не слизняк. my-primary-nav тоже не слаг.

Так как мы создали меню "My Awesome Menu" (в качестве примера), а слаг - "my-awesome-menu", вы можете получить его следующим образом:

$awesome_menu = wp_get_nav_menu_items( 'my-awesome-menu' );

Вы можете сами убедиться, что такое слаг, просто проверив базу данных в таблице wp_terms (или какой бы там ни был ваш префикс) и поищите там имя вашего меню.

Поскольку вы используете многоязычный сайт или даже мультисайт, этот метод не будет лучшим способом решения этой проблемы. Поскольку имя и слизняк могут отличаться.

Таким образом, лучший способ - получить все позиции меню с помощью get_nav_menu_locations(), которая будет возвращать ассоциативный массив, где ключ - это фрагмент зарегистрированного меню, а значение - это идентификатор термина меню, выбранного для его расположения.

Используя термин id, мы можем получить информацию об этих терминах, а затем вернуть соответствующий слаг, необходимый для функции.

Ниже приведена функция, которая использует функцию wp_get_nav_items(), но вы должны перейти в зарегистрированный слаг меню. В вашем случае это будет "первичным".

Кодовое решение

// kind of a long function name but whatevs
function get_menu_items_by_registered_slug($menu_slug) {

    $menu_items = array();

    if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_slug ] ) ) {
        $menu = get_term( $locations[ $menu_slug ] );

        $menu_items = wp_get_nav_menu_items($menu->term_id);


    }

    return $menu_items;

}
12
JoeMoe1984

Небольшая модификация принятого ответа

После удаления меню из его местоположения $locations[ $menu_slug ] возвращает 0, поэтому полезно добавить эту проверку:

function get_menu_items_by_registered_slug($menu_slug) {
  $menu_items = array();

  if ( ($locations = get_nav_menu_locations()) && isset($locations[$menu_slug]) && $locations[$menu_slug] != 0 ) {
    $menu = get_term( $locations[ $menu_slug ] );
    $menu_items = wp_get_nav_menu_items($menu->term_id);
  }

  return $menu_items;
}
1
Narek

Попробуй это:

    $menu_name = 'primary'; 

    if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
        $menu = wp_get_nav_menu_object( $locations[ $menu_name ] );

        $menu_items = wp_get_nav_menu_items($menu->term_id);
        // Your output code
    }
0
Ignat B.
custom_menu('primary');

function custom_menu( $theme_location ) {
if ( ($theme_location) && ($locations = get_nav_menu_locations()) && isset($locations[$theme_location]) ) {
    $menu = get_term( $locations[$theme_location], 'nav_menu' );
    $menu_items = wp_get_nav_menu_items($menu->term_id);
    //your menu code.
}
0
Abuzer Killibacak