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.
What is a WordPress Menu Item?
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.
Menu Item is actually a custom post type. The post type is nav_menu_item.
WordPress Menu WP_Post Object
Here is an example of a menu item of Sample Page. This is a page that comes with WordPress as an example page.
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.
Menu Item Attributes
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):
- ID: id of the saved menu item in the database or the term_id if the menu item represents a taxonomy term.
- attr_title: title attribute of the link element for this menu item.
- classes: The array of class attribute values for the link element of this menu item.
- db_id: The DB ID of this item as a nav_menu_item object, if it exists (0 if it doesn’t exist).
- description: The description of this menu item.
- menu_item_parent: The DB ID of the nav_menu_item that is this item’s menu parent, if any. 0 otherwise.
- object: The type of object originally represented, such as “category,” “post”, or “attachment.”
- object_id: The DB ID of the original object this menu item represents, e.g. ID for posts and term_id for categories.
- post_parent: The DB ID of the original object’s parent object, if any (0 otherwise).
- post_title: A “no title” label if menu item represents a post that lacks a title. This is not specific to menu item but good to know that it can be empty.
- target: The target attribute of the link element for this menu item.
- title: The title of this menu item. This is the actual text used when creating the link.
- type: The family of objects originally represented, such as “post_type” or “taxonomy.”
- type_label: The singular label used to describe this type of menu item.
- url: The URL to which this menu item points.
- xfn: The XFN relationship expressed in the link of this menu item. This is used as a rel attribute. Follow this link to read more about them.
- _invalid: Whether the menu item represents an object that no longer exists. If this is true, the menu item will not render.
Changing the WordPress Menu Item
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.
For this example we will use the “Sample Page” since we have seen an example of its WP_Post object. Let’s say that this page is a page which can be seen only by logged in users. We must then make the menu item for this page invalid so it won’t render.
So here we are first checking if we are in the admin area. If we are looking at the menu item in the admin area we want to have the unchanged menu item. After that we are checking the title of our menu item and if it is not “Sample Page” then we are returning the regular 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.
Various Scenarios
This filter can be used to change the menu items in various ways but most of them would probably be used to change the URL dynamically. Some of those scenarios could be:
- Having a Settings Page which dynamically get the query string for the user ID
- Hiding/Displaying a page based on the logged in status
- Hiding/Displaying a page based on the user role
- Dynamic Coupon URL which changes every day with a new coupon code
- Adding Google Analytics query strings (utm)
- Adding URL to Custom Links
Conclusion
WordPress Menu Items are easily extendable or editable. By using their attributes you can understand how to render a particular page or how not to render it 🙂
This is a great example of using filter hooks to allow the menu items to be changed if we need them to change.
Have you ever had a need to change a menu item or have a dynamically created menu item? Share your story with us!
Become a Sponsor
Nice post. Didn’t know it’s a custom post.
Great example, I’ve been able to use it to add a user specific icon to some of the menu items