#59224 closed defect (bug) (fixed)
get_pages: duplicate `WP_Query::get_posts` call
| Reported by: |
|
Owned by: |
|
|---|---|---|---|
| Milestone: | 6.3.2 | Priority: | normal |
| Severity: | normal | Version: | 6.3 |
| Component: | Posts, Post Types | Keywords: | has-patch commit fixed-major |
| Focuses: | performance | Cc: |
Description (last modified by )
The internal usage of WP_Query in get_pages (introduced in r55569 ) performs the WP_Query::get_posts() call twice ( see source:tags/6.3/src/wp-includes/post.php#L6094 ).
When query args are passed to the WP_Query constructor, it returns the result of the WP_Query::get_posts method call (proxied through WP_Query::query). All the fetched posts are then already present in the WP_Query object and the correct way to access those is via the WP_Query->posts property.
In case the WP_Query::get_posts() is used, a duplicate SQL query is performed, eventually leading to performance downgrade (yet the caching inside the WP_Query mitigates this to some degree, unless cache_results query param is set to true).
Anyway, I would propose to work with the WP_Query inside the get_pages in the similar way as the code does in the get_posts, where the query args are passed to the object through the WP_Query::query method it's return value (the found posts) is being used (see source:tags/6.3/src/wp-includes/post.php#L2440 ).
Attachments (1)
Change History (16)
#3
@
2 years ago
Thank you, @davidbinda, for providing the ticket and patch.
As you mentioned, the lack of extra query requests due to the wp_query cache explains why this went unnoticed. Well done on catching that detail.
The proposed changes are looks good to me.
#4
@
2 years ago
- Keywords commit added
Good catch @davidbinda.
Patch looks good to me. If other are happy, I will commit.
This ticket was mentioned in Slack in #core-performance by clarkeemily. View the logs.
2 years ago
This ticket was mentioned in PR #5114 on WordPress/wordpress-develop by joemcgill.
2 years ago
#8
This is a direct copy of 59224.diff from the original ticket. Opening the PR to allow CI to run before committing.
Trac ticket: https://core.trac.wordpress.org/ticket/59224
#11
@
2 years ago
- Keywords fixed-major added
- Resolution fixed deleted
- Status changed from closed to reopened
Reopening to be backported to the 6.3 branch.
joemcgill commented on PR #5114:
2 years ago
#12
Committed in 56491.
This ticket was mentioned in Slack in #core-performance by joemcgill. View the logs.
2 years ago
#15
@
2 years ago
As per your description, it sounds like there is a potential for optimizing the get_pages function to avoid unnecessary database queries. If you're looking to optimize and make changes to a WordPress Core function, there are a few general steps you'll want to follow:
- Create a Child Theme: Always create a [child theme](https://developer.wordpress.org/themes/advanced-topics/child-themes/) to ensure that updates to the main theme do not erase your customizations.
- Duplicate and Modify: In your child theme, duplicate the function that you want to change, renaming it to avoid function naming conflicts.
- Make Your Changes: Edit the new function to optimize it as per your needs.
- Use Your Custom Function: Replace calls to the original function with calls to your new, optimized function where needed.
However, considering your question, let's look at a more specific approach for optimizing the get_pages function based on your description:
- Use WP_Query Efficiently: Avoid calling
WP_Query::get_posts()twice, by utilizing the posts that are already fetched and available through theWP_Query->postsproperty.
- Modify or Create a Function: Write a new function or filter that uses the optimized method of querying posts/pages.
Here's a rough, theoretical example, as a basic reference to give you a starting point. This is not meant to be a direct solution, but rather a guideline:
`php
function optimized_get_pages( $args = array() ) {
... your extra code/logic ...
$query = new WP_Query( $args );
No need to call $query->get_posts() as we'll use $query->posts directly.
... possibly more of your code/logic ...
return $query->posts;
}
`
Now you would use optimized_get_pages() instead of get_pages() in your theme or plugin, to utilize the more optimized version of the function.
Note: The exact modification would greatly depend on the specific logic and requirements of your project, so adapt as necessary.
If you believe that this optimization should be part of the WordPress Core, consider creating a ticket on the [WordPress Trac](https://core.trac.wordpress.org/), or contribute to the [WordPress Core](https://make.wordpress.org/core/) directly. Always remember to test thoroughly to ensure that your changes do not introduce new issues or break existing functionality.
Uh, yea, I always suspected that [55569] will backfire eventually.
WP pages are not "just another post type", they have some specifics that all current code is expecting. Throwing away 14 years of incremental fixes and improvements for pages is not a good decision imho.
Changing the milestone to 6.3.2 as it would be best to fix this soon.