这可能会成为一个非常昂贵的操作,严重影响页面加载时间。在这个阶段,您的代码非常昂贵。让我们看看更好的方法来解决这个问题。
我们需要做的是尽量减少在db中花费的时间,要做到这一点,我们只会得到我们需要的信息,即post_author
post对象的属性。正如我们现在所看到的,没有任何本地方法可以post_author
来自数据库的属性WP_Query
, 我们只可能得到完整的对象或只是帖子ID
\'s、 要更改行为(和生成的SQL),我们将使用posts_fields
我们可以命令SQL查询只返回post_author
字段,这将节省我们在db中花费的大量时间,因为我们只得到我们需要的。
其次,为了提高性能,我们将告诉WP_Query
不缓存任何post数据或post术语和post元数据。由于我们不需要任何元数据或后期数据,我们可以简单地询问WP_Query
为了不查询这些数据并将其缓存以供以后使用,这也节省了我们在db上花费的大量额外时间,以及在缓存中添加这些数据的时间,我们还将节省db查询的时间。
让我们把这些全部放在代码中:(NOTE: 所有代码都未经测试,需要PHP 5.4+)
posts_fields
过滤器
add_filter( \'posts_fields\', function ( $fields, \\WP_Query $q ) use ( &$wpdb )
{
remove_filter( current_filter(), __FUNCTION__ );
// Only target a query where the new wpse_post_author parameter is set to true
if ( true === $q->get( \'wpse_post_author\' ) ) {
// Only get the post_author column
$fields = "
$wpdb->posts.post_author
";
}
return $fields;
}, 10, 2);
您会注意到,我们有一个名为
wpse_post_author
. 每当我们传递的值为
true
对于该自定义触发器,我们的过滤器将启动。
get_posts()
默认情况下,查询,get_posts()
通行证suppress_filters=true
到WP_Query
以避免过滤器作用于get_posts()
, 所以为了让我们的过滤器工作,我们需要将其设置回true。
另一个注意事项是,要可靠地获取当前类别,请使用$GLOBALS[\'wp_the_query\']->get_queried_object()
和$GLOBALS[\'wp_the_query\']->get_queried_object_id()
对于类别ID
if ( is_category() ) {
$current_category = get_term( $GLOBALS[\'wp_the_query\']->get_queried_object() );
$args = [
\'wpse_post_author\' => true, // To trigger our filter
\'posts_per_page\' => -1,
\'orderby\' => \'author\',
\'order\' => \'ASC\',
\'suppress_filters\' => false, // Allow filters to alter query
\'cache_results\' => false, // Do not cache posts
\'update_post_meta_cache\' => false, // Do not cache custom field data
\'update_post_term_cache\' => false, // Do not cache post terms
\'tax_query\' => [
[
\'taxonomy\' => $current_category->taxonomy,
\'terms\' => $current_category->term_id,
\'include_children\' => true
]
]
];
$posts_array = get_posts( $args );
if ( $posts_array ) {
// Get all the post authors from the posts
$post_author_ids = wp_list_pluck( $posts_array, \'post_author\' );
// Get a unique array of ids
$post_author_ids = array_unique( $post_author_ids );
// NOW WE CAN DO SOMETHING WITH THE ID\'S, SEE BELOW TO INCLUDE HERE
}
}
正如你所看到的,我用了
tax_query
, 由于它的灵活性,这是个人的偏好,而且,您可以在任何术语页面上重用代码,而无需修改它。在这种情况下,您只需更改
is_category()
条件
在我的tax_query
我已设置include_children
到true
, 也就是说WP_Query
将从当前类别以及属于所查看类别的子类别的帖子中获取帖子。这是所有分层术语页面的默认行为。如果您确实只需要查看类别中的作者,请设置include_children
到false
如果执行var_dump( $post_author_ids )
, 您将看到您有一个后作者ID数组。现在,您可以将这个ID数组传递给WP_User_Query
, 然后循环查看该查询的结果。
$user_args = [
\'include\' => $post_author_ids
];
$user_query = new \\WP_User_Query( $user_args );
var_dump( $user_query->results ); // For debugging purposes
if ( $user_query->results ) {
foreach ( $user_query->results as $user ) {
echo $user->display_name;
}
}
我们可以更进一步,在瞬间保存所有内容,这将使我们在=/-0.002s中只得到2个db查询。
瞬态要设置唯一的瞬态名称,我们将使用术语对象创建唯一的名称
if ( is_category() ) {
$current_category = get_term( $GLOBALS[\'wp_the_query\']->get_queried_object() );
$transient_name = \'wpse231557_\' . md5( json_encode( $current_category ) );
// Check if transient is set
if ( false === ( $user_query = get_transient( $transient_name ) ) ) {
// Our code above
// Set the transient for 3 days, adjust as needed
set_transient( $transient_name, $user_query, 72 * HOUR_IN_SECONDS );
}
// Run your foreach loop to display users
}
FLUSHING THE TRANSIENT
我们可以在发布新帖子或编辑、删除、取消删除帖子等时刷新瞬态。为此,我们可以使用
transition_post_status
钩您还可以将其调整为仅在某些事情发生时启动,例如仅在发布新帖子时。不管怎样,这是一个钩子,当柱子发生任何事情时,它会开火
add_action( \'transition_post_status\', function () use ( &$wpdb )
{
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient%_wpse231557_%\')" );
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient_timeout%_wpse231557_%\')" );
});
现在大家都在一起在函数类型文件中
add_filter( \'posts_fields\', function ( $fields, \\WP_Query $q ) use ( &$wpdb )
{
remove_filter( current_filter(), __FUNCTION__ );
// Only target a query where the new wpse_post_author parameter is set to true
if ( true === $q->get( \'wpse_post_author\' ) ) {
// Only get the post_author column
$fields = "
$wpdb->posts.post_author
";
}
return $fields;
}, 10, 2);
add_action( \'transition_post_status\', function () use ( &$wpdb )
{
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient%_wpse231557_%\')" );
$wpdb->query( "DELETE FROM $wpdb->options WHERE `option_name` LIKE (\'_transient_timeout%_wpse231557_%\')" );
});
在您的小部件中
if ( is_category() ) {
$current_category = get_term( $GLOBALS[\'wp_the_query\']->get_queried_object() );
$transient_name = \'wpse231557_\' . md5( json_encode( $current_category ) );
// Check if transient is set
if ( false === ( $user_query = get_transient( $transient_name ) ) ) {
$args = [
\'wpse_post_author\' => true, // To trigger our filter
\'posts_per_page\' => -1,
\'orderby\' => \'author\',
\'order\' => \'ASC\',
\'suppress_filters\' => false, // Allow filters to alter query
\'cache_results\' => false, // Do not cache posts
\'update_post_meta_cache\' => false, // Do not cache custom field data
\'update_post_term_cache\' => false, // Do not cache post terms
\'tax_query\' => [
[
\'taxonomy\' => $current_category->taxonomy,
\'terms\' => $current_category->term_id,
\'include_children\' => true
]
]
];
$posts_array = get_posts( $args );
$user_query = false;
if ( $posts_array ) {
// Get all the post authors from the posts
$post_author_ids = wp_list_pluck( $posts_array, \'post_author\' );
// Get a unique array of ids
$post_author_ids = array_unique( $post_author_ids );
$user_args = [
\'include\' => $post_author_ids
];
$user_query = new \\WP_User_Query( $user_args );
}
// Set the transient for 3 days, adjust as needed
set_transient( $transient_name, $user_query, 72 * HOUR_IN_SECONDS );
}
if ( false !== $user_query
&& $user_query->results
) {
foreach ( $user_query->results as $user ) {
echo $user->display_name;
}
}
}
编辑所有代码现在都已测试并按预期工作