概要
タグ同士の関連性(つながり)を定義することによって、似た投稿をたどっていけるようにする。
設計
第一に、あるタグと他のタグとの関連の強さは、共にタグ付けされている投稿の数として定義する。
たとえば「コミュニケーション」タグは91の投稿にタグ付けされている。このうち、
- 「コミュニケーション」と「会話」の両方でタグ付けされた投稿は13
- 「コミュニケーション」と「人間関係」の両方でタグ付けされた投稿は9
である。このとき「会話」は「人間関係」よりも「コミュニケーション」との関連性が高い(つながりが強い)。
第二に、関連の強さが同じタグ同士は、カウント(投稿に付けられている数)が多いタグを前に表示する。
たとえば「リーダーシップ」も「交渉」も、それぞれ5つの投稿において「コミュニケーション」と共にタグ付けされていて、「コミュニケーション」との関連性の高さは等しい。このときリーダーシップのカウントが40、交渉のカウントが30とすると、リーダーシップのほうが先に表示される。
実装
あるタグの関連タグを、関連性の高い順に並べる
関連性を調べたいタグ(以下ターゲットタグ)のIDを $term_id とする。
// 1 $post_query->posts = array{ post_id }
$post_query = new WP_Query( [
'post_type' => 'post',
'post_status' => 'publish',
'category_name' => 'list',
'tag_id' => $term_id,
'posts_per_page' => -1,
'fields' => 'ids',
] );
// 2 $term_query->terms = array{ term object }
$term_query = new WP_Term_Query( [
'taxonomy' => 'post_tag',
'object_ids' => $post_query->posts,
'exclude' => $term_id,
'fields' => 'all_with_object_id',
'update_term_meta_cache' => false,
] );
// 3 $postcount_by_tag = array{ term_id => postcount }
$postcount_by_tag = array_count_values(
array_column( $term_query->terms, 'term_id' )
);
// 4 $related_tags = array{ term_id => term object (w/postcount) }
foreach ( $term_query->terms as $term ) {
if ( ! isset( $related_tags[$term->term_id] ) ) {
$term->postcount = $postcount_by_tag[$term->term_id];
$related_tags[$term->term_id] = $term;
}
}
// 5
usort( $related_tags, function( $a, $b ) {
if( 0 === $ret = $b->postcount - $a->postcount ) {
$ret = $b->count - $a->count;
}
return $ret;
} );
- $term_id でタグづけされた公開リスト投稿のIDをすべて取得する。 $post_query->posts に投稿IDの配列が入る。あらかじめ何らかの投稿に付けられたタグについて処理が行われるので $term_id の存在チェックや投稿IDが返されないチェックは省略。
- 取得した全投稿に付けられたタグをすべて(ただしターゲットタグ自体は除いて)取得する。
'fields' => 'all_with_object_id'
によって、タグ付けされた投稿数だけタグオブジェクトが生成される(例えば、あるタグが5つの投稿にタグ付けされていれば5つのタグオブジェクトが生成される。それぞれのオブジェクトは object_id メンバによって区別される)。$term_query->terms にタグオブジェクトの配列が入る。 - タグIDをキー、タグIDの重複回数を値とした配列を作成。重複回数がNのとき、当該タグとそのタグはN個の投稿で共に使われていることを意味する。
- ソートするための配列を作成する。タグオブジェクトは重複しているので、タグIDにつき一つだけ利用する。またソートキーとして 重複回数をプロパティに加える。
- 重複回数の降順、タグカウントの降順でソートする。
関連タグをタグクラウドで表現する
// 1
array_walk( $related_tags, function( &$term, $key ){
$term->link = get_term_link( $term, 'post_tag' );
$term->id = $term->term_id;
} );
// 2
add_filter( 'tag_cloud_sort', function( $tags, $args ) use( $related_tags ){
return $related_tags;
}, 10, 2 );
// 3
$cloud = wp_generate_tag_cloud( current( $related_tags ), [
'number' => 0, // all
'smallest' => 1,
'largest' => 1.6,
'unit' => 'em',
'separator' => '',
] );
- タグクラウドを生成するのに必要な情報を追加する。
- 並べ替えた順序でタグクラウドを表示するためにフィルターフックにタグ配列を渡す。
- タグクラウドを生成する。2で渡す配列と同じ配列を渡すとフィルターフックが機能しない。空配列を渡しても機能しないため、ダミーとして2で渡す配列の先頭の要素だけを渡している。