我看不出有什么方法可以加快查询速度,但我们可以缓存结果。
不幸的是,没有可以绕过的钩子next_post_link()
和previous_post_link()
, 因此,我们必须用自定义函数替换这些函数。
以下示例代码使用post meta field 存储结果。可能会有副作用——我试图覆盖大多数病例,但可能遗漏了一些内容。
<?php # -*- coding: utf-8 -*-
namespace WPSE;
/* Plugin Name: Fast Next/Prev Post Links
* Plugin URI: https://wordpress.stackexchange.com/q/101435/
*/
add_action(
\'fast_prev_post_link\',
__NAMESPACE__ . \'\\fast_prev_post_link\',
10,
4
);
add_action(
\'fast_next_post_link\',
__NAMESPACE__ . \'\\fast_next_post_link\',
10,
4
);
add_action(
\'transition_post_status\',
__NAMESPACE__ . \'\\delete_fast_adjacent_meta\',
10,
3
);
/**
* Print previous post link.
*
* @param unknown_type $format
* @param unknown_type $link
* @param unknown_type $in_same_cat
* @param unknown_type $excluded_categories
*/
function fast_prev_post_link(
$format = \'« %link\',
$link = \'%title\',
$in_same_cat = FALSE,
$excluded_categories = \'\'
)
{
empty ( $format ) && $format = \'%link »\';
fast_adjacent_post_link(
$format,
$link,
$in_same_cat,
$excluded_categories,
TRUE
);
}
/**
* Print next post link.
*
* @param string $format
* @param string $link
* @param bool $in_same_cat
* @param array|string $excluded_categories
* @return void
*/
function fast_next_post_link(
$format = \'%link »\',
$link = \'%title\',
$in_same_cat = FALSE,
$excluded_categories = \'\'
)
{
empty ( $format ) && $format = \'%link »\';
fast_adjacent_post_link(
$format,
$link,
$in_same_cat,
$excluded_categories,
FALSE
);
}
/**
* Display adjacent post link.
*
* Slightly changed copy of adjacent_post_link().
* Unfortunately, WP mixes retrieving data and display. :(
*
* Can be either next post link or previous.
*
* @param string $format Link anchor format.
* @param string $link Link permalink format.
* @param bool $in_same_cat Whether link should be in a same
* category.
* @param array|string $excluded_categories Array or comma-separated list of
* excluded category IDs.
* @param bool $previous Default is true. Whether to display
* link to previous or next post.
* @return void
*/
function fast_adjacent_post_link(
$format,
$link,
$in_same_cat = FALSE,
$excluded_categories = \'\',
$previous = TRUE
)
{
if ( $previous && is_attachment() )
$post = get_post( get_post()->post_parent );
else // the only real change
$post = get_fast_adjacent_post(
$in_same_cat,
$excluded_categories,
$previous
);
if ( ! $post ) {
$output = \'\';
} else {
$title = $post->post_title;
if ( empty( $post->post_title ) )
$title = $previous ? __( \'Previous Post\' ) : __( \'Next Post\' );
$title = apply_filters( \'the_title\', $title, $post->ID );
$date = mysql2date( get_option( \'date_format\' ), $post->post_date );
$rel = $previous ? \'prev\' : \'next\';
$string = \'<a href="\' . get_permalink( $post ) . \'" rel="\'.$rel.\'">\';
$inlink = str_replace( \'%title\', $title, $link );
$inlink = str_replace( \'%date\', $date, $inlink );
$inlink = $string . $inlink . \'</a>\';
$output = str_replace( \'%link\', $inlink, $format );
}
$adjacent = $previous ? \'previous\' : \'next\';
echo apply_filters( "{$adjacent}_post_link", $output, $format, $link, $post );
}
/**
* Get next or previous post from post meta.
*
* @param bool $in_same_cat
* @param string|array $excluded_categories
* @param bool $previous
* @param object $post
* @return object|NULL Either the found post object or NULL
*/
function get_fast_adjacent_post(
$in_same_cat = FALSE,
$excluded_categories = array(),
$previous = TRUE,
$post = NULL
)
{
if ( ! $post = get_post( $post ) )
return;
$excluded_categories = prepare_excluded_categories( $excluded_categories );
$type = $previous ? \'prev\' : \'next\';
$cat_hash = empty ( $excluded_categories ) ? 0 : join( \'-\', $excluded_categories );
$hash = (int) $in_same_cat . "-$cat_hash";
$meta = (array) get_post_meta( $post->ID, "_fast_{$type}_post", TRUE );
if ( isset ( $meta[ $hash ] ) )
return get_post( $meta[ $hash ] );
$ad_post = get_adjacent_post( $in_same_cat, $excluded_categories, $previous );
if ( ! $ad_post )
return;
$meta[ $hash ] = $ad_post->ID;
update_post_meta( $post->ID, "_fast_{$type}_post", $meta );
return $ad_post;
}
/**
* Prepare categories sent as string.
*
* @param string|array $cats
* @return array
*/
function prepare_excluded_categories( $cats )
{
if ( empty ( $cats ) or is_array( $cats ) )
return array();
$cats = explode( \',\', $cats );
$cats = array_map( \'trim\', $excluded_categories );
$cats = array_map( \'intval\', $excluded_categories );
return $cats;
}
/**
* Deletes post meta values for the current post and all posts referencing it.
*
* @wp-hook transition_post_status
* @param string $new_status
* @param string $old_status
* @param object $post
* @return void
*/
function delete_fast_adjacent_meta( $new_status, $old_status, $post )
{
$prev = (array) get_post_meta( $post->ID, \'_fast_prev_post\', TRUE );
if ( ! empty ( $prev ) )
{
foreach ( $prev as $post_id )
delete_post_meta( $post_id, \'_fast_next_post\' );
}
$next = (array) get_post_meta( $post->ID, \'_fast_next_post\', TRUE );
if ( ! empty ( $next ) )
{
foreach ( $next as $post_id )
delete_post_meta( $post_id, \'_fast_prev_post\' );
}
delete_post_meta( $post->ID, \'_fast_prev_post\' );
delete_post_meta( $post->ID, \'_fast_next_post\' );
}
要使用这些功能,请将其添加到主题中:
do_action( \'fast_prev_post_link\' );
do_action( \'fast_next_post_link\' );