SYNCER

SYNCER

get_adjacent_post() - 前後の記事を取得する

公開日:

get_adjacent_post()は、隣接する前後の記事を取得する関数です。

構文

mixed get_adjacent_post( bool $in_same_term = false, array|string $excluded_terms = '', bool $previous = true, string $taxonomy = 'category' )

パラメータ

$in_same_term

初期値: false

同じタームの記事に限定して取得するか。

$excluded_terms

初期値: ''

取得の対象外とするタームのID。複数ある場合は、カンマ区切りの文字列、または配列で指定する。

$previous

初期値: true

前の投稿を取得する場合はtrue、次の投稿を取得する場合はfalseを指定する。

$taxonomy

初期値: 'category'

$in_same_termを有効にした場合に判定の対象となるタクソノミーの種類をスラッグで指定する。デフォルトではカテゴリーが対象となる。

返り値

mixed

取得できた場合は投稿オブジェクト。

グローバル変数の$postが設定されていない(現在の記事がない)場合はnull。

前の記事、または次の記事にあたる投稿が存在しなかった場合は空の文字列。

関数

この関数内で利用している、別のWordPress関数です。

  • AND()
  • IDNOTIN()
  • _deprecated_argument()
  • apply_filters() - フィルターイベントを発火する。
  • foreach()
  • get_current_user_id()
  • get_post()
  • get_post_stati()
  • get_post_type_object()
  • get_var()
  • prepare()
  • term_idIN()
  • wp_cache_get()
  • wp_cache_set()
  • wp_get_object_terms()

フック

関数内で呼び出されるイベントです。

フィルター

  • get_{$adjacent}_post_excluded_terms
  • get_{$adjacent}_post_join
  • get_{$adjacent}_post_where
  • get_{$adjacent}_post_sort

サンプルコード

この章のサンプルは全て、この記事を現在の記事として実行しています。意図した記事を取得できているか確認してみて下さい。

前の記事を取得する

引数を指定しなければ、単純に、現在の1つ前の記事(古い記事)を取得します。

php

<?php
	// 実行 (前の記事を取得)
	$result = get_adjacent_post() ;

	// 結果
	var_dump( $result ) ;

結果 (出力内容) - PHP7.0.13

object(WP_Post)#310 (24) {
  ["ID"]=>
  int(7)
  ["post_author"]=>
  string(1) "1"
  ["post_date"]=>
  string(19) "2016-12-13 13:22:54"
  ["post_date_gmt"]=>
  string(19) "2016-12-13 04:22:54"
  ["post_content"]=>
  string(578) "※この記事の投稿IDは<code>7</code>です。

SYNCERのイメージキャラクターを紹介します。ビギナー中里さんに依頼し、描いていただきました。
http://hcrossc.com/

[caption id="attachment_8" align="aligncenter" width="400"]<a href="https://wp.syncer.jp/mascot/syncer-bot/" rel="attachment wp-att-8"><img src="https://wp.syncer.jp/wp-content/uploads/2016/12/syncer-bot.png" alt="イメージキャラクター" width="400" height="405" class="size-full wp-image-8" /></a> SYNCERのイメージキャラクターです。[/caption]"
  ["post_title"]=>
  string(39) "SYNCERのイメージキャラクター"
  ["post_excerpt"]=>
  string(0) ""
  ["post_status"]=>
  string(7) "publish"
  ["comment_status"]=>
  string(6) "closed"
  ["ping_status"]=>
  string(6) "closed"
  ["post_password"]=>
  string(0) ""
  ["post_name"]=>
  string(6) "mascot"
  ["to_ping"]=>
  string(0) ""
  ["pinged"]=>
  string(0) ""
  ["post_modified"]=>
  string(19) "2016-12-13 19:20:28"
  ["post_modified_gmt"]=>
  string(19) "2016-12-13 10:20:28"
  ["post_content_filtered"]=>
  string(0) ""
  ["post_parent"]=>
  int(0)
  ["guid"]=>
  string(25) "https://wp.syncer.jp/?p=7"
  ["menu_order"]=>
  int(0)
  ["post_type"]=>
  string(4) "post"
  ["post_mime_type"]=>
  string(0) ""
  ["comment_count"]=>
  string(1) "0"
  ["filter"]=>
  string(3) "raw"
}

次の記事を取得する

第3引数をfalseにすれば、1つ次の記事(新しい記事)を取得できます。

php

<?php
	// 実行 (次の記事を取得)
	$result = get_adjacent_post( false, "", false ) ;

	// 結果
	var_dump( $result ) ;

結果 (出力内容) - PHP7.0.13

object(WP_Post)#310 (24) {
  ["ID"]=>
  int(20)
  ["post_author"]=>
  string(1) "1"
  ["post_date"]=>
  string(19) "2016-12-13 18:22:48"
  ["post_date_gmt"]=>
  string(19) "2016-12-13 09:22:48"
  ["post_content"]=>
  string(533) "SYNCERで利用している正方形のロゴを紹介します。サービスのココナラで依頼して作成していただきました。

[caption id="attachment_21" align="aligncenter" width="256"]<a href="https://wp.syncer.jp/syncer%e3%81%ae%e6%ad%a3%e6%96%b9%e5%bd%a2%e3%83%ad%e3%82%b4/square-logo/" rel="attachment wp-att-21"><img src="https://wp.syncer.jp/wp-content/uploads/2016/12/square-logo.jpg" alt="SYNCERのロゴ" width="256" height="256" class="size-full wp-image-21" /></a> SYNCERの正方形ロゴ[/caption]"
  ["post_title"]=>
  string(24) "SYNCERの正方形ロゴ"
  ["post_excerpt"]=>
  string(0) ""
  ["post_status"]=>
  string(7) "publish"
  ["comment_status"]=>
  string(6) "closed"
  ["ping_status"]=>
  string(6) "closed"
  ["post_password"]=>
  string(0) ""
  ["post_name"]=>
  string(60) "syncer%e3%81%ae%e6%ad%a3%e6%96%b9%e5%bd%a2%e3%83%ad%e3%82%b4"
  ["to_ping"]=>
  string(0) ""
  ["pinged"]=>
  string(0) ""
  ["post_modified"]=>
  string(19) "2016-12-13 19:23:15"
  ["post_modified_gmt"]=>
  string(19) "2016-12-13 10:23:15"
  ["post_content_filtered"]=>
  string(0) ""
  ["post_parent"]=>
  int(0)
  ["guid"]=>
  string(26) "https://wp.syncer.jp/?p=20"
  ["menu_order"]=>
  int(0)
  ["post_type"]=>
  string(4) "post"
  ["post_mime_type"]=>
  string(0) ""
  ["comment_count"]=>
  string(1) "0"
  ["filter"]=>
  string(3) "raw"
}

同じタクソノミーから取得する

デフォルトでは全体の中から前の記事、次の記事を取得しますが、第1引数をtrueにし、第4引数でタクソノミーの種類(デフォルトではカテゴリ)を指定すれば、同じ系統の記事を取得できます。例えば、第4引数をpost_tagにすれば同じカテゴリではなく同じタグから取得できます。

php

<?php
	// 実行 (同じカテゴリの次の記事を取得)
	$result = get_adjacent_post( true, "", false, "category" ) ;

	// 結果
	var_dump( $result ) ;

結果 (出力内容) - PHP7.0.13

object(WP_Post)#308 (24) {
  ["ID"]=>
  int(16)
  ["post_author"]=>
  string(1) "1"
  ["post_date"]=>
  string(19) "2016-12-13 19:17:54"
  ["post_date_gmt"]=>
  string(19) "2016-12-13 10:17:54"
  ["post_content"]=>
  string(315) "※この記事の投稿IDは<code>16</code>です。

2015年9月、八景島シーパラダイスに行った時に見かけた可愛いペンギン。スタッフさんと仲が良いですね。

[video width="640" height="360" mp4="https://wp.syncer.jp/wp-content/uploads/2016/12/cute-penguin.mp4"][/video]"
  ["post_title"]=>
  string(36) "可愛いシーパラのペンギン"
  ["post_excerpt"]=>
  string(0) ""
  ["post_status"]=>
  string(7) "publish"
  ["comment_status"]=>
  string(6) "closed"
  ["ping_status"]=>
  string(6) "closed"
  ["post_password"]=>
  string(0) ""
  ["post_name"]=>
  string(7) "penguin"
  ["to_ping"]=>
  string(0) ""
  ["pinged"]=>
  string(0) ""
  ["post_modified"]=>
  string(19) "2016-12-13 19:19:23"
  ["post_modified_gmt"]=>
  string(19) "2016-12-13 10:19:23"
  ["post_content_filtered"]=>
  string(0) ""
  ["post_parent"]=>
  int(0)
  ["guid"]=>
  string(26) "https://wp.syncer.jp/?p=16"
  ["menu_order"]=>
  int(0)
  ["post_type"]=>
  string(4) "post"
  ["post_mime_type"]=>
  string(0) ""
  ["comment_count"]=>
  string(1) "0"
  ["filter"]=>
  string(3) "raw"
}

ソースコード

wp-includes/link-template.php

/**
 * Retrieves the adjacent post.
 *
 * Can either be next or previous post.
 *
 * @since 2.5.0
 *
 * @global wpdb $wpdb WordPress database abstraction object.
 *
 * @param bool         $in_same_term   Optional. Whether post should be in a same taxonomy term. Default false.
 * @param array|string $excluded_terms Optional. Array or comma-separated list of excluded term IDs. Default empty.
 * @param bool         $previous       Optional. Whether to retrieve previous post. Default true
 * @param string       $taxonomy       Optional. Taxonomy, if $in_same_term is true. Default 'category'.
 * @return null|string|WP_Post Post object if successful. Null if global $post is not set. Empty string if no
 *                             corresponding post exists.
 */
function get_adjacent_post( $in_same_term = false, $excluded_terms = '', $previous = true, $taxonomy = 'category' ) {
	global $wpdb;

	if ( ( ! $post = get_post() ) || ! taxonomy_exists( $taxonomy ) )
		return null;

	$current_post_date = $post->post_date;

	$join = '';
	$where = '';
	$adjacent = $previous ? 'previous' : 'next';

	if ( $in_same_term || ! empty( $excluded_terms ) ) {
		if ( ! empty( $excluded_terms ) && ! is_array( $excluded_terms ) ) {
			// back-compat, $excluded_terms used to be $excluded_terms with IDs separated by " and "
			if ( false !== strpos( $excluded_terms, ' and ' ) ) {
				_deprecated_argument( __FUNCTION__, '3.3.0', sprintf( __( 'Use commas instead of %s to separate excluded terms.' ), "'and'" ) );
				$excluded_terms = explode( ' and ', $excluded_terms );
			} else {
				$excluded_terms = explode( ',', $excluded_terms );
			}

			$excluded_terms = array_map( 'intval', $excluded_terms );
		}

		if ( $in_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 '';
			$term_array = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'ids' ) );

			// Remove any exclusions from the term array to include.
			$term_array = array_diff( $term_array, (array) $excluded_terms );
			$term_array = array_map( 'intval', $term_array );

			if ( ! $term_array || is_wp_error( $term_array ) )
				return '';

			$where .= " AND tt.term_id IN (" . implode( ',', $term_array ) . ")";
		}

		/**
		 * Filters the IDs of terms excluded from adjacent post queries.
		 *
		 * The dynamic portion of the hook name, `$adjacent`, refers to the type
		 * of adjacency, 'next' or 'previous'.
		 *
		 * @since 4.4.0
		 *
		 * @param string $excluded_terms Array of excluded term IDs.
		 */
		$excluded_terms = apply_filters( "get_{$adjacent}_post_excluded_terms", $excluded_terms );

		if ( ! empty( $excluded_terms ) ) {
			$where .= " AND p.ID NOT IN ( SELECT tr.object_id FROM $wpdb->term_relationships tr LEFT JOIN $wpdb->term_taxonomy tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id) WHERE tt.term_id IN (" . implode( ',', array_map( 'intval', $excluded_terms ) ) . ') )';
		}
	}

	// 'post_status' clause depends on the current user.
	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;
		}

		/*
		 * Results should include private posts belonging to the current user, or private posts where the
		 * current user has the 'read_private_posts' cap.
		 */
		$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 ? 'DESC' : 'ASC';

	/**
	 * Filters the JOIN clause in the SQL for an adjacent post query.
	 *
	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
	 * of adjacency, 'next' or 'previous'.
	 *
	 * @since 2.5.0
	 * @since 4.4.0 Added the `$taxonomy` and `$post` parameters.
	 *
	 * @param string  $join           The JOIN clause in the SQL.
	 * @param bool    $in_same_term   Whether post should be in a same taxonomy term.
	 * @param array   $excluded_terms Array of excluded term IDs.
	 * @param string  $taxonomy       Taxonomy. Used to identify the term used when `$in_same_term` is true.
	 * @param WP_Post $post           WP_Post object.
	 */
	$join = apply_filters( "get_{$adjacent}_post_join", $join, $in_same_term, $excluded_terms, $taxonomy, $post );

	/**
	 * Filters the WHERE clause in the SQL for an adjacent post query.
	 *
	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
	 * of adjacency, 'next' or 'previous'.
	 *
	 * @since 2.5.0
	 * @since 4.4.0 Added the `$taxonomy` and `$post` parameters.
	 *
	 * @param string $where          The `WHERE` clause in the SQL.
	 * @param bool   $in_same_term   Whether post should be in a same taxonomy term.
	 * @param array  $excluded_terms Array of excluded term IDs.
	 * @param string $taxonomy       Taxonomy. Used to identify the term used when `$in_same_term` is true.
	 * @param WP_Post $post           WP_Post object.
	 */
	$where = apply_filters( "get_{$adjacent}_post_where", $wpdb->prepare( "WHERE p.post_date $op %s AND p.post_type = %s $where", $current_post_date, $post->post_type ), $in_same_term, $excluded_terms, $taxonomy, $post );

	/**
	 * Filters the ORDER BY clause in the SQL for an adjacent post query.
	 *
	 * The dynamic portion of the hook name, `$adjacent`, refers to the type
	 * of adjacency, 'next' or 'previous'.
	 *
	 * @since 2.5.0
	 * @since 4.4.0 Added the `$post` parameter.
	 *
	 * @param string $order_by The `ORDER BY` clause in the SQL.
	 * @param WP_Post $post    WP_Post object.
	 */
	$sort  = apply_filters( "get_{$adjacent}_post_sort", "ORDER BY p.post_date $order LIMIT 1", $post );

	$query = "SELECT p.ID FROM $wpdb->posts AS p $join $where $sort";
	$query_key = 'adjacent_post_' . md5( $query );
	$result = wp_cache_get( $query_key, 'counts' );
	if ( false !== $result ) {
		if ( $result )
			$result = get_post( $result );
		return $result;
	}

	$result = $wpdb->get_var( $query );
	if ( null === $result )
		$result = '';

	wp_cache_set( $query_key, $result, 'counts' );

	if ( $result )
		$result = get_post( $result );

	return $result;
}

参考リンク