WordPress のフォーラムに「個別投稿ページにカテゴリー アーカイブ ページへ戻るリンクを設置したい」というような内容のトピックが上がっていたので、回答しようと思案していたら・・・別の方法で解決していました。
既に、脳内ではコードが完成(?)していたので、ここで吐き出そうと思います。
いろいろな方法(JavaScript、セッション、Cookie、URL パラメータ、フォーム パラメータおよびリファラー等)が考えられますが、真っ先に思いついたのが、現在の投稿が最近の投稿から数えて何番目なのかを取得してページ数を算出し、リンクを作成する方法でした。
現在の投稿が何番目かを取得
まずは、単純に現在の投稿が何番目かを取得してみます。
コードは下記のようになります。
<?php
$where = $wpdb->prepare( "WHERE p.post_date >= %s AND p.post_type = %s AND p.post_status = 'publish'", $post->post_date, $post->post_type );
$sql = "SELECT COUNT(*) FROM $wpdb->posts AS p $where ORDER BY p.post_date DESC";
$number = (int)$wpdb->get_var( $sql );
echo "<p>現在の投稿は $number 番です。</p>";
?>
上記コードをベースに、非公開の投稿やカテゴリーに対応させて汎用的な関数にしたのが、下記の get_post_number 関数となります。
get_post_number 関数
/**
* 投稿の番号を取得します。
*
* @global wpdb $wpdb
*
* @param bool $previous オプション。古い順に数えた番号を取得するかどうか。デフォルトは false。
* @param bool $same_term オプション。投稿が同じタクソノミーかどうか。デフォルトは false。
* @param string $taxonomy オプション。タクソノミー。デフォルトは 'category'。
* @return int|null 番号。エラー時は null。
*/
function get_post_number( $previous = false, $same_term = false, $taxonomy = 'category' ) {
global $wpdb;
if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
return null;
$current_post_date = $post->post_date;
$join = '';
$where = '';
if ( $same_term ) {
$join .= " INNER JOIN $wpdb->term_relationships AS tr ON p.ID = tr.object_id INNER JOIN $wpdb->term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id";
$where .= $wpdb->prepare( "AND tt.taxonomy = %s", $taxonomy );
if ( ! is_object_in_taxonomy( $post->post_type, $taxonomy ) )
return null;
$terms = get_the_terms( $post->ID, $taxonomy );
if ( $terms ) {
$terms = wp_list_sort( $terms, array( 'term_id' => 'ASC' ) );
$term = $terms[0];
$where .= " AND tt.term_id = {$term->term_id}";
}
}
if ( is_user_logged_in() ) {
$user_id = get_current_user_id();
$post_type_object = get_post_type_object( $post->post_type );
if ( empty( $post_type_object ) ) {
$post_type_cap = $post->post_type;
$read_private_cap = 'read_private_' . $post_type_cap . 's';
} else {
$read_private_cap = $post_type_object->cap->read_private_posts;
}
$private_states = get_post_stati( array( 'private' => true ) );
$where .= " AND ( p.post_status = 'publish'";
foreach ( (array) $private_states as $state ) {
if ( current_user_can( $read_private_cap ) ) {
$where .= $wpdb->prepare( " OR p.post_status = %s", $state );
} else {
$where .= $wpdb->prepare( " OR (p.post_author = %d AND p.post_status = %s)", $user_id, $state );
}
}
$where .= " )";
} else {
$where .= " AND p.post_status = 'publish'";
}
$op = $previous ? '<=' : '>=';
$order = $previous ? 'ASC' : 'DESC';
$where = $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s $where", $current_post_date, $post->post_type );
$sql = "SELECT COUNT(*) FROM $wpdb->posts AS p $join $where ORDER BY p.post_date $order";
$number = (int)$wpdb->get_var( $sql );
return $number;
}
使用例:
<?php
$number = get_post_number();
echo "<p>現在の投稿は $number 番です。</p>";
?>
アーカイブ ページのリンクを取得
ページ番号を指定してタクソノミー アーカイブ ページのリンクを取得する関数が、下記のコードの get_archive_link_by_page_number 関数です。
get_archive_link_by_page_number 関数
/**
* 指定のページ番号のアーカイブページのリンクを取得します。
*
* @global WP_Rewrite $wp_rewrite
*
* @param int $page ページ番号。
* @param bool $same_term オプション。投稿が同じタクソノミーかどうか。デフォルトは false。
* @param string $taxonomy オプション。タクソノミー。デフォルトは 'category'。
* @return strin|null URL。エラー時は null。
*/
function get_archive_link_by_page_number( $page, $same_term = false, $taxonomy = 'category' ) {
global $wp_rewrite;
if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
return null;
if ( $same_term ) {
$terms = get_the_terms( $post->ID, $taxonomy );
if ( $terms ) {
$terms = wp_list_sort( $terms, array( 'term_id' => 'ASC' ) );
$link = get_term_link( $terms[0], $taxonomy );
}
} else {
$link = get_post_type_archive_link( $post->post_type );
}
if ( 1 < $page ) {
$format = $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';
$link = trailingslashit( $link ). str_replace( '%#%', $page, $format );
}
return $link;
}
使用例:
<?php
$number = get_post_number( false, true, 'category' );
$posts_per_page = (int)get_option( 'posts_per_page' );
if ( $number && $posts_per_page ) {
$page_number = (int)ceil( $number / $posts_per_page );
$link = get_archive_link_by_page_number( $page_number, true );
echo '<a href="' . esc_url( $link ) . '">カテゴリーアーカイブページへ戻る</a>';
}
?>
制限事項
タームが複数設定されている場合は、パーマリンクと同じターム(ターム ID が最も小さいターム)へのリンクとなります。