WordPress.org

Make WordPress Core

Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#28126 closed defect (bug) (fixed)

wp_nav_menu defaults to 'first' non-empty menu, without specifying an order.

Reported by: thingalon Owned by: wonderboymusic
Milestone: 4.0 Priority: normal
Severity: normal Version: 3.9
Component: Menus Keywords:
Focuses: Cc:

Description

According to the wp_nav_menu documentation, it should display the first non-empty menu if called with no parameters. (Documentation link: http://codex.wordpress.org/Function_Reference/wp_nav_menu)

However, 'first' is neither defined in the documentation, nor in code. It displays the first non-empty menu found by an unsorted query.

For example, if I call wp_nav_menu();, the following query is used:

SELECT t.*, tt.* FROM wp_terms AS t INNER JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy IN ('nav_menu')

I suggest the following change, which selects the first non-empty menu by name:

  • wp-includes/nav-menu-template.php

     
    280280       // get the first menu that has items if we still can't find a menu
    281281       if ( ! $menu && !$args->theme_location ) {
    282                $menus = wp_get_nav_menus();
     282               $menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
    283283               foreach ( $menus as $menu_maybe ) {
    284284                       if ( $menu_items = wp_get_nav_menu_items( $menu_maybe->term_id, array( 'update_post_term_cache' => false ) ) ) {

That will at least produce reliably consistent results, and remains consistent with the order that nav menus are displayed in wp-admin.

Alternately, the problem may be the documentation; it may need to be made clearer that the 'first' item is arbitrarily selected.

Attachments (1)

nav-menu-template.diff (593 bytes) - added by lukecarbis 6 years ago.

Download all attachments as: .zip

Change History (11)

#1 @SergeyBiryukov
6 years ago

  • Milestone changed from Awaiting Review to 4.0

#2 @lukecarbis
6 years ago

  • Keywords has-patch added

Great pickup thingalon. I've attached a diff that does exactly what you suggested.

#3 @wonderboymusic
6 years ago

  • Owner set to wonderboymusic
  • Resolution set to fixed
  • Status changed from new to closed

In 28826:

When selecting a fallback menu in wp_nav_menu(), the "first" menu is retrieved from an unsorted query. When retrieving a fallback menu, pass array( 'orderby' => 'name' ) to wp_get_nav_menus() to return a menu consistently.

Props lukecarbis.
Fixes #28126.

#4 @nacin
6 years ago

  • Keywords dev-feedback added; has-patch removed
  • Resolution fixed deleted
  • Status changed from closed to reopened

I'm concerned that this will suddenly change people's sites as they were used to it being a different sort. While MySQL makes zero guarantees as to the order of records when there is no ORDER BY, they are more likely to be returned in insertion order than by name.

wp_get_nav_menus() specifically is 'orderby' => 'none' by default, which seems to be the bug here.

I'm not sure what to do or whether this actually has real world implications, but I want another opinion.

#5 @helen
6 years ago

I don't think it really has real world implications - while I could be missing situations where the passed args are actually an empty array somehow, a search through a couple hundred themes doesn't pull up any straight calls to wp_nav_menu(). It would be kind of a strange thing to do.

Does seem like we should consistently order them across the board, though. Not sure if that's something for 4.0 at this point.

#6 @pento
6 years ago

I think I'm okay with this change. MySQL's behaviour for return unsorted rows is not possible to define - it's different between storage engines, and even between different versions of the same storage engine (example).

If a site were in a position to be affected by this change, then they would probably have already been hit by it when their host updated their MySQL server at some point.

This ticket was mentioned in IRC in #wordpress-dev by pento. View the logs.


6 years ago

#8 @pento
6 years ago

  • Keywords dev-feedback removed
  • Resolution set to fixed
  • Status changed from reopened to closed

I've opened #29460 to investigate changing the default orderby to name in wp_get_nav_menus().

This ticket was mentioned in IRC in #wordpress-dev by SergeyBiryukov. View the logs.


6 years ago

This ticket was mentioned in IRC in #wordpress-dev by SergeyBiryukov. View the logs.


6 years ago

Note: See TracTickets for help on using tickets.