Opened 4 years ago
Closed 4 years ago
#51829 closed defect (bug) (duplicate)
BUG: get_queried_object() in pre_get_posts hook crashes author archive page get_queried_object() call
Reported by: |
|
Owned by: | |
---|---|---|---|
Milestone: | Priority: | normal | |
Severity: | normal | Version: | 5.5.3 |
Component: | Query | Keywords: | |
Focuses: | Cc: |
Description
Lets call get_queried_object()
on wp
action:
<?php add_action( 'wp', function(){ var_dump( get_queried_object() ); // on author archive page //> object(WP_User) // on single post page //> object(WP_Post) // on category page //> object(WP_Post) } );
Now do the same, but call get_queried_object()
on pre_get_posts
action before:
<?php add_action( 'wp', function(){ var_dump( get_queried_object() ); // on author archive page //> bool(false) // on single post page //> object(WP_Post) // on category page //> object(WP_Post) } ); add_action( 'pre_get_posts', function(){ get_queried_object(); } );
As we can see we lose WP_User object in this case.
Why it happens?
Because get_queried_object()
get user only by 'author'
parameter:
<?php } elseif ( $this->is_author ) { $this->queried_object_id = (int) $this->get( 'author' ); $this->queried_object = get_userdata( $this->queried_object_id ); }
but WP_Query::parse_query()
sets $this->is_author
by 'author_name'
parameter too (not only 'author'):
<?php if ( empty( $qv['author'] ) || ( '0' == $qv['author'] ) ) { $this->is_author = false; } else { $this->is_author = true; } if ( '' !== $qv['author_name'] ) { $this->is_author = true; }
So get_queried_object()
can't properly set user object when only 'author_name'
query_var is set by request.
The 'author'
query_var is sets later by WP_Query::get_posts()
:
<?php // Author stuff for nice URLs. if ( '' !== $q['author_name'] ) { if ( strpos( $q['author_name'], '/' ) !== false ) { $q['author_name'] = explode( '/', $q['author_name'] ); if ( $q['author_name'][ count( $q['author_name'] ) - 1 ] ) { $q['author_name'] = $q['author_name'][ count( $q['author_name'] ) - 1 ]; // No trailing slash. } else { $q['author_name'] = $q['author_name'][ count( $q['author_name'] ) - 2 ]; // There was a trailing slash. } } $q['author_name'] = sanitize_title_for_query( $q['author_name'] ); $q['author'] = get_user_by( 'slug', $q['author_name'] ); if ( $q['author'] ) { $q['author'] = $q['author']->ID; } $whichauthor .= " AND ({$wpdb->posts}.post_author = " . absint( $q['author'] ) . ')'; }
But it's too late and the earlier call of get_queried_object()
already setup the $wp_query->queried_object
property to NULL.
What to do?
I think it's better to setup 'author'
query_var from 'author_name'
query_var earlier in WP_Query::parse_query()
method, but not in WP_Query::get_posts()
.
Hi there, welcome back to WordPress Trac!
Thanks for the report, we're already tracking this issue in #27015.