Improvements to the metadata API in WordPress 6.3

WordPress 6.3 brings significant improvements to the metadata 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., enhancing the lazy loading capabilities for term, comment, and site metadata. These enhancements aim to improve performance, optimize code readability, and ensure a consistent developer experience across different metadata types.

For context: Lazy loading metadata in WordPress refers to a technique where metadata associated with various elements, such as terms, is loaded only when it is actually needed. Instead of fetching and loading all metadata upfront, the metadata is deferred to a queue until the specific metadata type is requested, reducing unnecessary database queries or cache lookups and improving overall performance. 

Term metadata lazy loading improvements

Term 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. in WordPress has always been lazily loaded since its introduction in WordPress 4.4. However, this behavior was only applicable to WP_Query. In other CoreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. components like WP_Term_Query, term meta was always primed by default, unless developers explicitly set the update_term_meta_cache parameter to false. Unfortunately, many developers overlooked this parameter, resulting in unnecessary loading of term meta. 

In WordPress 6.3, WP_Term_Query has been improved so that instead of priming term meta, which involves performing a database or cache lookup, terms are now added to a queue dedicated to loading term meta. This queue, implemented as an array stored in memory, offers excellent performance. Additionally, it allows developers to conveniently include term IDs if they anticipate requiring them later. Only when the first call to get_term_meta is made, will all the term meta be primed in a single request.

To facilitate the lazy loading of term meta, a new function called wp_lazyload_term_meta() has been introduced in Core. This function provides an efficient mechanism for handling term meta and contributes to optimizing the overall performance of WordPress. To use, pass an array of term IDs to the function like this: 

wp_lazyload_term_meta( array( 1, 2, 3 ) );

For more information, please check out the original ticketticket Created for both bug reports and feature development on the bug tracker. #57645.

WordPress 6.3 introduces further enhancements to the handling of term meta in WP_Query.  Currently, in the WP_Query class, the function wp_queue_posts_for_term_meta_lazyload is invoked, which adds the term IDs of all terms linked to the queried posts into the lazy load metadata queue. Improvements to this function were made in WordPress 6.2, which improved the performance of this function by utilizing wp_cache_get_multiple()

In this new release, an unnecessary check to verify term existence has been eliminated. As a result, when wp_queue_posts_for_term_meta_lazyload() is called, it no longer executes get_term for every individual term ID, as it is highly unlikely that the term would not exist. See #57966

There were also a number of other places where term meta was not loaded at all as it is completely unneeded. See #58230, #57701

Comment metadata lazy loading improvements

Similar to term meta, comment meta in WordPress was previously lazily loaded only within the context of WP_Query. Now, rather than priming comment meta in the WP_Comment_Query class, it is added to the lazily loaded metadata queue and loaded only when used. This keeps the logic consistent between term and comment meta and also makes the code much more readable. As a result, the wp_queue_comments_for_comment_meta_lazyload() function, which is now unnecessary, has been deprecated. See #57801, #58301

Site metadata is now lazily loaded

Site meta was introduced in #40647 and allows developers to extend 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 functionality by adding metadata to a site on the multisite. Site meta is not to be confused with networknetwork (versus site, blog) meta, which is used for network options. Site meta is only used in one place in core and designed for 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 use. 

Previously, when calling WP_Site_Query or get_sites(), developers had to pass an update_site_meta_cache parameter to the query to ensure that site meta was not primed, resulting in a cache lookup or database query. Now, whenever update_site_meta_cache is true, site ids are added to the queue to be lazily loaded. If get_site_meta() is called, all the IDs in the queue are loaded in a single call. 

A new function has been added in core to add site IDs to the queue called wp_lazyload_site_meta(). It can be used by passing an array of site IDs, like this:

wp_lazyload_site_meta( array( 1, 2, 3 ) );

For more information, please check out the original ticket #58185.

General improvements to the Lazy loading API

The WP_Metadata_Lazyloader class, responsible for lazy loading metadata, underwent a significant refactor to enhance code maintainability. As part of this refactoring, the lazyload_term_meta and lazyload_comment_meta methods of the class have been deprecated. These methods have been replaced with a more versatile lazyload_meta_callback method, which can be reused for any metadata type. 

If your code currently utilizes the lazyload_term_meta and lazyload_comment_meta methods, it is recommended that you transition to using lazyload_meta_callback. This improvement allows for easy extension of the metadata data API to support additional metadata types in the future, such as posts and users.

Further enhancements were made to the lazy loading metadata API. A check is now implemented to verify if the requested ID is already present in the queue before processing. Here’s an example scenario: Let’s say your page request has added three items (IDs 5, 6, and 7) to the metadata lazy loading queue. However, when you call the get_term_meta function, you request ID 9, which is not in the queue. Previously, this would have led to an additional database or cache lookup. With the latest improvement, the queue is checked before processing to see if the current ID is already in the queue. If it’s not, the ID is added to the queue, preventing unnecessary lookups. See #57901

There have been significant changes in how metadata is handled for comments, terms, and sites. In the updated implementation, the prime meta parameters in functions such as _prime_term_cache() and WP_Term_Query are always respected. However, instead of directly priming the meta, it is now added to the metadata queue. Previously, there were inconsistencies in these functions and classes. For example, in _prime_term_cache(), if the term was already present in the cache, the term meta would not be primed. This led to a confusing developer experience and degraded performance.

Now, with the latest improvements, adding an ID to the queue has minimal to no performance impact when requested. As a result, these functions and classes are expected to behave in a more predictable manner. Developers can rely on consistent behavior and improved performance regarding metadata handling for comments, terms, and sites. See #57227

Props to @flixos90 and @joemcgill for peer review, to @stevenlinx, @leonnugraha and @costdev for review.

#6-3, #dev-notes, #dev-notes6-3