0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[WordPress] 投稿に作成者と別に監修者を設定して、作成者別アーカイブで合わせて表示

Posted at

やりたいこと

  • 投稿に作成者とは別に「監修者」のカスタムフィールドを用意してWordPressのユーザーを紐付けておく
  • 作成者別アーカイブで該当ユーザーの作成した投稿(デフォルト)以外に監修者に設定されてる投稿も混ぜて表示する

監修者カスタムフィールド

コードではなくカスタムフィールド系プラグインでさっと作成

作成者アーカイブ

WordPressの作成者アーカイブは癖が強いです。
pre_get_postsフックあるいはサブクエリで作成者アーカイブのクエリを改変(その作成者の投稿と、監修者カスタムフィールドにその作成者が付与されている投稿を混ぜる)すれば一見正しいコードに見えます。ただし、元々のクエリの作成者情報に引きづられてページ送りなどがすごく影響を受けます。

やってみて影響を受けたもの

  1. 投稿と監修者の投稿と合わせたとき、本来のユーザーの投稿数より 多い と、ページ送りはできる(生成される)けど、最後の方のページが404と判定され投稿が表示されない。
  2. pre_get_posts フックで作成者アーカイブの時にクエリ改変する。このとき author_name があると1の影響あったため、削除する。ページ送りできるようになるが、ユーザー情報を使う部分で不具合(titleタグなど)が出る。

ということはpre_get_postsの後に実行されるアクションフック(今回は wp)で、削除したauthor_name, author をセットし直したらいいんじゃね?となります。

実際のコード

作成者アーカイブでのプログラムの流れはこんな感じ

  1. ユーザーが作成者の投稿IDを配列で取得しておく
  2. ユーザーが監修者カスタムフィールドで紐付けられているの投稿IDを配列で取得しておく
  3. pre_get_posts フックにおいて、作成者アーカイブの場合、author_nameを空白にセット、1, 2の投稿のみをセットしたクエリにする
  4. wp フックで作成者アーカイブの場合、3で削除(空白をセット)されたauthor_name, authorを戻す
<?php
// ユーザーが作成者の投稿IDを取得
function get_author_post_id( $user_id ) {
	if ( empty( $user_id ) ) {
		return;
	}
	$post_id = array();
	$posts_array = get_posts( array(
		'posts_per_page' => -1,
		'author' => $user_id,
		'fields' => 'ids',
	) );
	if ( ! empty( $posts_array ) ) {
		$post_id = $posts_array;
	}
	return $post_id;
}
// ユーザーが監修者の投稿IDを取得
function get_supervisor_post_id( $user_id ) {
	if ( empty( $user_id ) ) {
		return;
	}
	$post_id = array();
	$posts_array = get_posts( array(
		'posts_per_page' => -1,
		'meta_key' => 'post_supervisor', // 監修者カスタムフィールドのキー
		'meta_value' => $user_id,
		'fields' => 'ids',
	) );
	if ( ! empty( $posts_array ) ) {
		$post_id = $posts_array;
	}
	return $post_id;
}

function mod_pre_get_posts( $query ) {
	if ( is_admin() || ! $query->is_main_query() ){
		return;
	}
	if ( $query->is_author() ) { // 作成者アーカイブの場合
		//クエリ改変
		$userdata = get_user_by( 'slug', get_query_var( 'author_name' ) );
		$userid   = $userdata->ID;
		$user_main_post_id = (array) get_author_post_id( $userid );
		$user_sub_post_id  = (array) get_supervisor_post_id( $userid );
		$user_posts_ids = array_merge( $user_main_post_id, $user_sub_post_id );
		$user_posts_ids = array_unique( $user_posts_ids );
		$user_posts_ids = array_values( $user_posts_ids );

		$query->set( 'author_name', '' ); // これをセットしないとページ送りができなくなる
		$query->set( 'post__in', $user_posts_ids );
	}
}
add_action( 'pre_get_posts', 'mod_pre_get_posts' );

// wp のアクションフックで削除した author_name, author をセットし直す。これを実施しないとクエリを参照にして実行される関数に影響が出る
function mod_wp_author() {
	if ( is_author() ) { // 作成者アーカイブの場合
		global $wp_query;
		$username = $wp_query->query[ 'author_name' ];
		$userdata = get_user_by( 'slug', $username );
		$userid   = $userdata->ID;
		set_query_var( 'author_name', $username );
		set_query_var( 'author', $userid );
	}
}
add_action( 'wp', 'mod_wp_author' );

こういったクエリの改変のコードを書いたときに便利なプラグインが「Query Monitor」になります。
https://ja.wordpress.org/plugins/query-monitor/

実際に呼ばれてるクエリやどんなフックで何が実行されているかを確認できます。

現場からは以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?