Taxonomy performance improvements in WordPress 6.0

As part of the 6.0 release of WordPress, the new performance team has been hard at work to improve the performance of term queries. There are many term queries on the average page load and improving these improves the performance of WordPress in general. 

Improvement to term query caching. 

Queries run by WP_Term_Query have been cached since 4.6. The way these caches are primed and handled has been improved in WordPress 6.0.

Removing to cache limit

Prior to WordPress 6.0, term query caches were limited to a 24-hour period for those using persistent object caching. This limitation is now removed, so if caches are not invalidated, it means that term query should cache much longer. For inactive sites or overnight, caches should remain primed, which should improve site performance. 

For more information, see #54511.

Term query cache only caches the term ID

Term query caches have been changed so that instead of caching the whole term object, now only the term IDs are cached. This means that the value stored in cache will be much smaller (in terms of memory) and will not fill up memory in session or persistent object cache.

Once all the IDs for the terms are loaded, the _prime_term_cache function is called. This loads into memory terms that are not already in cache. If the term is already in memory, then it is not loaded again, which is a performance benefit. On an average page load, a term may be requested multiple times, like the case of a tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) archive page. Early in the page load, get_term_by, will prime the term cache and all other calls, such as get_the_terms, will have the term already primed in page memory. This results, in most cases in fewer and smaller queries that are run against the term table. 

For more information, see #37189.

Improved term query cache key generation

Previously, similar term queries that have similar cache keys would result in basically the same query being run twice on a single page load. Because all queries now only get the term ID and store it in cache (see above), the cache exactly the same. For example, you create a call to get_terms where you request all categories and return only the field slug. If you do the same query and request only the name, then this would hit the same cache.

Another improvement is the handling of parameters that can be passed to WP_Term_Query that can be ambiguous. Fields like slug that can be either a string or an array are now converted to always be an array, meaning that the likelihood of reusing a cache is higher as the cache key is the same, no matter which type of parameter is passed. 

For more information, see #55352.

Improve performance for navigation menuNavigation Menu A theme feature introduced with Version 3.0. WordPress includes an easy to use mechanism for giving various control options to get users to click from one place to another on a site. items

Convert wp_get_nav_menu_items to use a taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. query

This replaces usage of get_objects_in_term function with a simple taxonomy query. This replacement converts the use of two queries to get the menu items to use one simple query. This saves one query for each menu requested and adds consistency. 

For more information, see #55372.

Prime all term and posts caches in wp_get_nav_menu_items

The wp_get_nav_menu_items function now calls _prime_term_cache and _prime_post_cache for all objects linked to menu items. If a menu contains a list of categories and pages, all the related objects are now primed in two cache calls (one for terms and one for posts). This will result in far fewer requests to the database and cache.

For more information, see #55428.

Convert term_exists to use get_terms

The function term_exists has now been converted to use get_terms ( WP_Term_Query ) internally replacing raw uncached database queries. This function was one of the last places to perform raw queries to the terms table in the database. Using the get_terms function has a number of key benefits, including: 

  • Consistency with other coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. functions like get_term_by
  • The ability to filterFilter Filters are one of the two types of Hooks They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. the results.
  • Results of get_terms are cached 

term_exists is designed for back-end use and is mostly used in core functions designed to write data to the term table. However, term_exists can and is used by some theme and pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the Plugin Directory or can be cost-based plugin from a third-party developers. This results in raw uncachable and unfilterable queries to be run on the front-end of a site. 

Now that term_exists is cached, custom import / migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. tools may need to check if they correctly cache invalidation terms. If your importation code is using core functions like wp_insert_term, then there is no need to do anything, as core does its own cache invalidation for you. However, if you are writing data to the term table manually, then you may need to call the clean_term_cache function. 

For those that need to ensure that term_exists is getting an uncached result, there are two ways to do this:

  1. Using the new term_exists_default_query_args filter 
$callback = function ( $args ) {
   $args['cache_domain'] = microtime();
add_filter( 'term_exists_default_query_args',  $callback );
$check = term_exists( 123, 'category' );
remove_filter( 'term_exists_default_query_args',  $callback );
  1. Using wp_suspend_cache_invalidation
wp_suspend_cache_invalidation( true );
$check = term_exists( 123, 'category' );
wp_suspend_cache_invalidation( false );

For more information, see #36949.

Add a limit to taxonomy queries

The ​​WP_Tax_Query class is used in WP_Query to limit queries by term. Under the hood, ​​WP_Tax_Query uses ​​WP_Term_Query, which means that ​​WP_Tax_Query will get the benefits of the cache improvements documented above. The ​​WP_Tax_Query run, which transforms term slugs / names into term IDs to be queried, now has a limit added to it. This query limit improves the performance of the query, as well as improves the likelihood of an existing cache query to continue to exist in the object cache. For example, a standard tag archive calls get_term_by and primes the cache. By the time it gets to the ​​WP_Tax_Query, that query is being loaded from cache. This removes one query per tag archive page. 

For more information, see #55360.

Props to @milana_cap, @mxbclang, @flixos90 for peer review.

#6-0, #dev-notes, #dev-notes-6-0, #performance, #users

Controlling access to REST API user functionality for multisite

Following last week’s discussion in #core-multisite (read the recap) this week’s office hours agenda was to continue the chat about the multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site-related enhancements for the REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) users endpoint, focussing heavily on how to access the required functionality. Here is a wrap-up of the discussion.

Chat log in #core-multisite

Attendees: @jeremyfelt, @jnylen, @nerrad, @ipstenu, @earnjam, @kenshino, @maximeculea, @mikelking, @lukecavanagh, @flixos90

Now that the way on how one should be able to modify user roles per site was clarified last week, this week the focus laid on where one should be able to perform those actions. The current state of the wp-json/wp/v2/users endpoint in multisite is:

  • The users overview accessible with a GET request to wp-json/wp/v2/users only lists users that are part of the current site.
  • When creating a user with a POST request to wp-json/wp/v2/users, that user is created and added to the current site. When providing the roles parameter, the passed roles are added to the user, otherwise the user will still be part of the site, but without any role. See #38526 for background.
  • It is possible to both read and edit any user from any site with a request to wp-json/wp/v2/users/<id>, regardless of whether the user is part of that site.
  • A DELETE request to wp-json/wp/v2/users/<id> results in an error. See #38962 for background.

After the discussion about how to be able to add a specific user to a site, update their site capabilities and remove them from a site, this week’s chat revolved around where these actions can be accessed, as they are for the most part networknetwork (versus site, blog)-specific actions not available to a site administrator. The approach that was agreed on is:

  • The users overview at wp-json/wp/v2/users should continue to only show users of that site by default, but a request like wp-json/wp/v2/users?global=true should show all users in the WordPress setup. This parameter must only be available to network administrators though, more specifically users with the manage_network_users capability. In the future a network parameter might also be introduced for support of multi networks, but at this point coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. does not support querying users per network. Accessing global users should be available from all sites in a setup instead of only from the main site. While this approach makes these endpoints duplicates of each other, it has several benefits like preventing the requirement for cross-domain requests, allowing easier APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. discovery and not requiring the main site of a setup to be exposed to REST API calls to a sub site.
  • Assigning an existing user to a site and removing a user from a site should generally be only available to network administrators, and the site administrators of the site that is being interacted with.
  • Similarly, editing a user that does not belong to the current site should only be possible for a network administrator. Currently this is available to site administrators as well which is probably wrong.
  • Deleting any user completely should only be available to a network administrator. A good way to handle the reassign parameter needs to be found though.

Before coming to the conclusion that dealing with multisite functionality at the existing users endpoint, the possibility of introducing a multisite-specific endpoint only available on the main site was discussed. However this was considered not practical due to the nature of how users work in WordPress. Having separate endpoints for other network-wide functionality might still be a possibility though as long as that component solely affects the network adminadmin (and super admin), so this idea is something to keep in mind for thought about further network functionality endpoints in the future.

Back to the users endpoint, one related question that came up is:

  • Should the sites a user belongs to be available at the wp-json/wp/v2/users endpoint or at a future wp-json/wp/v2/sites endpoint? If they were available in the wp-json/wp/v2/users endpoint, every user entity would have a new sites key available if the current user had sufficient permissions to see these. If they were available in the wp-json/wp/v2/sites endpoint, that endpoint could easily support this functionality through usage of a user parameter.

@jeremyfelt suggested to look at the “Add New User” screen in the site admin to have a good use-case for how to scaffold the multisite functionality of the API endpoint. This has helped during this week’s office-hours and can also be beneficial in the future. Eventually this screen should be revamped entirely, being powered by the REST API.

Regarding the enhancements of the users endpoint, a general ticketticket Created for both bug reports and feature development on the bug tracker. for this task was opened at #39544. This ticket is meant to be used for discussion on the topic, while separate smaller tickets should be opened for actually implementing the individual pieces. For now feedback is welcome on that ticket. The discussion on multisite improvements for the REST API will continue at Tuesday 17:00 UTC.

/cc @rmccue and @kadamwhite



#multisite, #networks-sites, #rest-api, #users

Improving the REST API users endpoint in multisite

One of the objectives for multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site is sorting how users are managed with the REST APIREST API The REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) This was one of the agenda items for last week’s #core-multisite office hours and generated some good discussion. Here’s a wrap-up of the ideas and thoughts from that discussion.

Chat log in #core-multisite

Attendees: @iamfriendly, @johnjamesjacoby, @nerrad, @florian-tiar, @mikelking, @earnjam, @jeremyfelt

Users in multisite exist globally and are shared among sites on one or more networks. Users are associated with sites in the user metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. table with a wp_#_capabilities key.

The current state of the wp-json/wp/v2/users endpoint for multisite is:

  • A POST request for a new global user to the main site creates the user and associates them with the main site only.
  • A POST request for a new global user to a sub site creates the user and associates them with the sub site only.
  • A POST request for an existing global user results in an error.
  • A PUT request for an existing global user to a sub site updates the user’s meta with a capability for that sub site.
  • A DELETE request on multisite is invalidinvalid A resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. and results in an error. See #38962.

It is not possible to remove a user from an individual site or to delete the user from the networknetwork (versus site, blog).

Previous tickets: #38526, #39155, #38962, #39000

The following are a few thoughts expressed separately from the above summary.

  • The right way to associate existing objects over the REST API is with a PUT request.
  • The right way to disassociate existing objects is with a PUT request.
  • Linked previous discussion – “Deleting an item should always delete an item
  • We already have functions like remove_user_from_blog() and add_user_to_blog() available to us.
  • Does “add” invite or literally add? This can probably be included as data in the PUT request.
  • What happens if an APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. client is built for single site and then that site gets switched to multisite?
  • Handling bulk actions on an endpoint would be nice. (e.g. Add a user to multiple sites) No endpoint has implemented batch handling yet though.

Initial tasks:

  • It should be possible to remove a user from a site with a PUT request to the wp-json/wp/v2/users/# endpoint.
  • It should be possible to delete a global user with a DELETE request to the wp-json/wp/v2/users/# endpoint once all sites have been disassociated.

New tickets will be created soon for these tasks. Please leave any initial feedback in the comments on this post covering the assumptions and conclusions made above. There will be another round of discussion during tomorrow’s #core-multisite office hours at Tuesday 17:00 UTC.

/cc @rmccue and @kadamwhite

#multisite, #networks-sites, #rest-api, #users

Manage Users redesigned. Added ability …

Manage Users redesigned. Added ability to query users by role. Still a work in progress.

#ui, #users