WordPress 現在の投稿は何番目?

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 $same_term オプション。投稿が同じタクソノミーかどうか。デフォルトは false。
 * @param string $taxonomy オプション。タクソノミー。デフォルトは 'category'。
 * @param bool $previous オプション。古い順に数えた番号を取得するかどうか。デフォルトは false。
 * @return int|null 番号。エラー時は null。
 */
function get_post_number( $same_term = false, $taxonomy = 'category', $previous = false ) {
	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( true );
$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 が最も小さいターム)へのリンクとなります。

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。