Wp_setup_nav_menu_item

0 views
Skip to first unread message

Favio Cassidy

unread,
Aug 3, 2024, 3:49:24 PM8/3/24
to styltaimaros

How does your walker class look like? You may not need the my_plugin_wp_setup_nav_menu_item filter if you use the value of $item->post_content insted of $item->description. Also make sure to print the raw value of the menu item description without escaping it with esc_html or esc_attr.

While looking into a memory consumption of navigation menus on some blogs with huge menus, I have noticed that to decorate a nav menu item via wp_setup_nav_menu_item function generates a lot of data.

IMHO, in case of a WordPress install with a persistent object cache backend, it would be beneficial to cache the fully decorated nav menu item (output of the wp_setup_nav_menu_item) in order to bring that from cache on subsequent requests instead of decorating the nav menu item over and over.

However, I don't think that caching the decorated nav menu is something what core should do by default (eg.: it does not make sense w/o persistent object cache backend), so I wonder if it would make sense to add a short-circuit filter to the wp_setup_nav_menu_item function which would allow plugins to implement the caching layer.

Not sure why the description was reverted though. It's not a big deal but generally using the same word (Returning) in different contexts in the same sentence is considered poor usage of the English language. Imho the edited description is better and clearer.

Not sure why the unit test was refactored. Also not sure what is being tested now. The original test was testing the output of the wp_setup_nav_menu_item() function after the filter was used. The current test doesn't seem to be testing anything?

The current test ensures that wp_setup_nav_menu_item() applies the pre_wp_setup_nav_menu_item filter exactly once. I agree though that when testing the output specifically, it might be preferable to use a custom callback instead.

WordPress Menu Items were unknown to me before I had to create a custom navigation item which has a dynamic URL based on the logged in user. I will introduce you to the WordPress Menu Item as a component which you can easily change as you want.

WordPress Menu Item is actually a WordPress Post Object. Each item we have in our navigation can be represented and read as a WP_Post object. The attributes such as post_title which are basic in a regular WP_Post object can be empty here and they are not used when our navigation is rendered.

If you have entered two menu items from a same page, then there will be two WP_Post objects with the same attributes except the IDs and probably the post_parent. Every Menu Item we do create in WordPress is saved in the database *wp_prefix*_posts.

We will not go into how each menu item is constructed but if you are really interested you can check in the file wp-includes/nav-menu.php. The function used to build those menus is wp_setup_nav_menu_item.

There are several attributes specific to menu items. If you have worked with regular WP_Post object and have taken a look at the above WP_Post object you could recognise that there are some attributes which do not exist in a regular WP_Post object. Let me describe each one for you (description is mostly taken from the function mentioned above):

Now that we know which attributes can be used or accessed then we can easily change our menu items. To change each menu item you can use the filter to which the menu item object is passed in the previously mentioned function. This filter is wp_setup_nav_menu_item.

Otherwise, we are checking if the user is logged in and if it is not, then we are making that menu item invalid. We are also checking for the URL value, which if empty, makes the menu item also invalid.

This post is about a coding pattern I have never seen used by anyone else for writing guard clauses, especially when those guard clauses are complex. This pattern results in code that is significantly more reliable, maintainable and easier to write than using either nested conditionals OR early returns.

But first, let us review the cargo cultism of using early returns. Google return early pattern and you will find literally pages of advocacy for returning early. Here are examples from the first two (2) search result pages:

Frankly, the answer is simple. Returning early can result in code that is easier to read and follow compared with having only one return statement at the end of a function and using complex conditionals to enable that one return statement.

To illustrate how difficult code with conditional complex logic can be to comprehend by only reading it consider an example that does not return early. From the WordPress core codebase I have copied wp_setup_nav_menu_item() below, but with comments removed to make the code shorter.

Avoiding multiple return points in a function/method is the most common argument against returning early, even though some argue the old admonition to always have one exit point in a subroutine is old-school thinking and that returning early is more enlightened than those old school laggards.

But I cannot state emphatically enough how infuriating it is to set a breakpoint on a return statement, run the debugger, and have it continue beyond the intended breakpoint because some jerk programmer decided to return early in the function being breakpointed.

This is not a mere inconvenience. Multiple returns in code often takes significantly longer for the developer debugging the code to track down and breakpoint all the potentially relevant return statements, restart the debugger, and then repeat the process until they are able to understand what they were trying to understand in the first place.

Sure, not every function will need shared exit code, but when it is needed you will either have to abandon the pattern or refactor the code to allow it to more easily share common exit code, which may or may not be the ideal way to structure your code.

While this may be harder to understand at first, once you start using the alternative I propose I submit you will soon discover how limiting it can be do not be able to use an early bypass branch more than once per function or method.

c80f0f1006
Reply all
Reply to author
Forward
0 new messages