ショートコードでカスタム投稿一覧を呼び出す。ターム、n番目など細かく制御

ワードプレス

カスタムフィールド中に突然、

「ある投稿タイプの最新記事を1件だす。」

「別のフィールドに、ある投稿タイプの2番目に新しい記事を1件だす。」

ということが必要になり、

「まぁ、これはショートコードで処理するのが簡単かな。」と思い、作ってみました。

※2020/4/2

1:エラー処理が足りなかった、オプションを大量に追加、などで全面書き換えしました。

2:「get_field」「the_field」等はACFプラグインが無いとエラーを出します。

インストールだけでもするか、

あるいは該当箇所を

・get_post_meta( $post->ID, ‘○○○’, true ) )

・echo get_post_meta( $post->ID, ‘○○○’, true ) )

などに書き換えてください。

関数

2021年12月7日書き換え

  • 著者の絞り込みの誤りを修正
  • アーカイブへのリンクに投稿タイプ名を追加
  • 編集リンクを追加

//サブループ呼び出し
//呼び出し例 
//ページツリー使う場合の引数例「post_type="page" parent="recruit"」
function show_subloop( $atts ){
	global $post;
	$sentence = '';

//投稿タイプ
if( !empty( $atts['post_type'] ) ){
	$post_type = $atts['post_type'];
}else{
	$post_type = 'post';
}
$post_type_name = get_post_type_object( $post_type );
$post_type_label = $post_type_name->labels->name;

//表示数
if( !empty( $atts['show'] ) ){
	$show = $atts['show'];
}else{
	$show = 4;
}

//オフセット
if( !empty( $atts['offset'] ) ){
	$offset = $atts['offset'];
}else{
	$offset = 0;
}

//除外ターム
if( !empty( $atts['exclude_term'] ) ){
	$exclude_term = $atts['exclude_term'];
}else{
	$exclude_term = '';
}

//著者絞り込み
if( !empty( $atts['author'] ) ){
	$author_id = get_user_by( 'slug', $atts['author'] )->id;
}else{
	$author_id = '';
}

//カスタムフィールド値で絞り込み
if( !empty( $atts['meta_key'] ) && !empty( $atts['meta_value'] ) ){
	$meta_key = $atts['meta_key'];
	$meta_value = $atts['meta_value'];
	$meta_compare = 'LIKE';
}

//ループのタイトル
if( !empty( $atts['term'] ) && $atts['term'] === 'current' ){
	$terms = get_the_terms( $post->ID, $atts['tax'] );
	foreach ( $terms as $term ) {
		$term_slug = $term->slug;
		$term_name = $term->name;
		break;
	}
	$expost = get_the_ID();
	$title = '<h2 class="loop-title shortcode-loop-title"><span class="slug">' . $term_slug . '</span><span class="page-language">' . $term_name . '</span></h2>';
}elseif( !empty( $atts['title'] ) ){
	if( !empty( $atts['title_slug'] ) ){
		$title = '<h2 class="loop-title shortcode-loop-title"><span class="slug">' . $atts['title_slug'] . '</span><span class="page-language">' . $atts['title'] . '</span></h2>';
	}else{
		$title = '<h2 class="shortcode-loop-title">' . $atts['title'] . '</h2>';
	}
}else{
	$title = '';
}

//アーカイブへのリンク
if( !empty( $atts['term'] ) && $atts['term'] === 'current' ){
	$term_name = get_term_by( 'slug', $term_slug, $atts['tax'] )->name;
	if( $term_name ){
		$archive_link_url = get_term_link( $term_slug, $atts['tax'] );
		$archive_link_anker = $term_name . 'の' . $post_type_label . '一覧';
	}
}elseif( !empty( $atts['tax'] ) && !empty( $atts['term'] ) ){
	$term_name = get_term_by( 'slug', $atts['term'], $atts['tax'] )->name;
	if( $term_name ){
		$archive_link_url = get_term_link( $atts['term'], $atts['tax'] );
		$archive_link_anker = $term_name . 'の' . $post_type_label . '一覧';
	}
}elseif( !empty( $atts['author'] ) ){
	$author_id = get_user_by( 'slug', $atts['author'] )->id;
	$archive_link_url = get_author_posts_url( $author_id );
	$archive_link_anker = get_the_author_meta( 'display_name', $author_id ) . 'の' . $post_type_label . '一覧';
}else{
	$archive_link_url = get_post_type_archive_link( $post_type );
	$archive_link_anker = $post_type_label . '一覧';
}
if( !empty( $atts['archive_link_anker'] ) ){
	$archive_link_anker = $atts['archive_link_anker'];		
}
if( !empty( $atts['archive_link'] ) && $atts['archive_link'] === 'false' ){
}else{
	$archive_link = '<div class="shortcode-loop-archive-link link-related"><a href="' . $archive_link_url . '">' . $archive_link_anker . '</a></div>';
}

//ラッパーにID付与
if( !empty( $atts['id'] ) ){
	$id = ' id="' . $atts['id'] . '"';
}else{
	$id = '';
}

//ラッパーにクラス付与
if( !empty( $atts['class'] ) ){
	$class = ' ' . $atts['class'];
}else{
	$class = '';
}
if( !empty( $atts['term'] ) && $atts['term'] === 'current' ){
	$class .= ' term-' . $term_slug;
}
//.article-containerにクラス付与
if( !empty( $atts['style'] ) && $atts['style'] == 'text' ){
	$container_class = ' display-text';
}elseif( !empty( $atts['style'] ) && $atts['style'] == 'thumbnail' ){
	$container_class = ' display-thumbnail';
}elseif( !empty( $atts['style'] ) && $atts['style'] == 'grid' ){
	$container_class = ' flex-container flex-dir-row display-grid-l flex-c4 flex-768-css flex-414-css flex-375-css flex-320-css';
	$article_flex = ' flex-child';
}elseif( !empty( $atts['style'] ) && $atts['style'] == 'sidebar' ){
	$container_class = ' display-sidebar';
}else{
	$container_class = ' display-text';
}

//投稿にクラス付与
if( !empty( $atts['article_class'] ) ){
	$article_class = ' ' . $atts['article_class'];
}else{
	$article_class = '';
}

//設置ページのID
$location_id = get_the_ID();

//親ページのID取得
if( !empty( $atts['parent'] ) ){
	$parent_data = get_page_by_path( $atts['parent'] );
	$parent_ID = $parent_data->ID;
}

//WPPのデータ取得
if( function_exists( 'wpp_get_mostpopular' ) ){
$wpp_args = array(
	'range' => 'last30days',
	'order_by' => 'views',
	'post_type' => 'column',
);
$wpp_query = new WPP_Query( $wpp_args );
$rank_data = $wpp_query->get_posts();
}

//▲ループ外処理ここまで▲

//出力条件
if( !empty( $atts['tax'] ) && !empty( $atts['term'] ) ){
	if( $atts['term'] === 'current' ){
		$args = array(
			'post_type' => $post_type,
			'posts_per_page'	=> $show,
			'post__not_in' => array( $expost ),
			'tax_query' => array(
				array(
					'taxonomy'	=> $atts['tax'],
					'field'		=> 'slug',
					'terms'		=> $term_slug
				)
			)
		);
	}else{
		$args = array(
			'post_type' => $post_type,
			'tax_query' => array(
				array(
					'taxonomy'	=> $atts['tax'],
					'field'		=> 'slug',
					'terms'		=> $atts['term'],
				),
			),
			'posts_per_page'	=> $show,
			'offset'			=> $offset,
			'meta_key'			=> $meta_key,
			'meta_value'		=> $meta_value,
			'meta_compare'		=> $meta_compare,
		);
	}
	$query = new WP_Query( $args );
}elseif( !empty( $atts['tax'] ) && !empty( $atts['exclude_term'] ) ){
	$args = array(
		'post_type'			=> $post_type,
		'tax_query' => array(
			array(
				'taxonomy'	=> $atts['tax'],
				'field' => 'slug',
				'terms' => $exclude_term,
				'operator' => 'NOT IN'
			),
		),
		'author'			=> $author_id,
		'posts_per_page'	=> $show,
		'offset'			=> $offset,
		'post_parent'		=> $parent_ID,
		'meta_key'			=> $meta_key,
		'meta_value'		=> $meta_value,
		'meta_compare'		=> $meta_compare,
	);
	$query = new WP_Query( $args );
}else{
	$args = array(
		'post_type'			=> $post_type,
		'author'			=> $author_id,
		'posts_per_page'	=> $show,
		'offset'			=> $offset,
		'post_parent'		=> $parent_ID,
		'meta_key'			=> $meta_key,
		'meta_value'		=> $meta_value,
		'meta_compare'		=> $meta_compare,
	);
	$query = new WP_Query( $args );
}
	if( $query->have_posts() ){
		$sentence .= '<div class="loop-container">'  . "\n" . '<div' . $id . ' class="shortcode-loop shortcode-loop-' . $post_type . $class . '">' . "\n" . '<div class="loop-title-container archive-tille-container shortcode-loop-header">' . $title . "\n" . '</div>' . "\n" . '<div class="article-container flex-dir-row' . $container_class . '">' . "\n";
		while( $query->have_posts() ){
			$query->the_post();

//▼ループ内処理ここから▼

//ID比較
$article_id = get_the_ID();
if( $location_id == $article_id ){
	$current = ' current';
}else{
	$current = '';
}

//著者表示
if( !empty( $atts['show_author'] ) && $atts['show_author'] == 'true' ){
	$author_display = '<p class="author"><span class="fn">' . get_the_author_posts_link() . '</p>';
}else{
	$author_display = '';
}

//アバター
if( !empty( $atts['avatar'] ) && $atts['avatar'] == 'true' ){
	$avatar = '<a href="' . get_author_posts_url( $post->post_author ) . '" class="a-avatar" style="background-image: url(' . get_avatar_url( $post->post_author ) . ');"></a>';
}

//日付
if( !empty( $atts['date'] ) && $atts['date'] == 'false' ){
	$date = '';
}else{
	$date_status = ' date-display-true';
	$date = '<p class="date date-published">' . get_the_date() . '</p>';
}

//記事タイトル
if( !empty( $atts['title_length'] ) ){
	$length = $atts['title_length'];
	$more = ' …';
	$post_title = wp_html_excerpt( the_title_attribute( 'echo=0' ), $length, $more );
//	$post_title = mb_strimwidth( strip_tags( the_title_attribute( 'echo=0' ) ), 0, $length, '', 'UTF-8' );
}else{
	$post_title = the_title_attribute( 'echo=0' );
}

//要約
if( !empty( $atts['excerpt'] ) && $atts['excerpt'] == 'false' ){
	$excerpt = '';
}else{
	$excerpt = '<div class="entry-content entry-body excerpt-container">' . mb_strimwidth( strip_tags( $post->post_content ), 0, 92, '…', 'UTF-8' ) . '</div>';
}

//ページ内リンク
if( !empty( $atts['samepage'] ) && $atts['samepage'] == 'true' ){
	$link = '#post-' . get_the_ID();
	$self_id = ' id="link-post-' . get_the_ID() . '"';
}else{
	if( get_post_meta( $post->ID, 'post_linknone', true ) ){
		$article_link_class = ' article-link-none';
		$link_url = '';
		$link_class = ' link-none';
		$link_more = 'false';
	}elseif( get_post_meta($post->ID, 'post_linkurl', true ) ){
		$link_url = ' href="' . get_post_meta( $post->ID, 'post_linkurl', true ) . '"';
		$link_class = ' link-optional';
		if( get_post_meta($post->ID, 'post_link_blank', true ) ){
			$link_target = ' target="_blank" rel="noreferrer noopener"';
			$link_class = ' link-optional link-ext';
		}
	}else{
		$link_url = ' href="' . get_permalink() . '"';
	}
	$self_id = ' id="post-' . get_the_ID() . '"';
}

//サムネール
$thumbnail_size = 'thumbnail-169';
$default_thumbnail = get_stylesheet_directory_uri() . '/images/' . $thumbnail_size . '-default.png';
if( has_post_thumbnail() && !post_password_required() ){
	$image_url = get_the_post_thumbnail_url( get_the_ID(), $thumbnail_size );
}else{
	$image_url = $default_thumbnail;
}
$image_style = ' style="background-image: url( '.$image_url.' );"';
if( !empty( $atts['thumbnail'] ) && $atts['thumbnail'] == 'true' ){
	$thumbnail = '<a class="article-image' . ' aspect-' . $thumbnail_size . '" href="' . get_permalink() . '"' . $image_style . '></a>';
	$thumbnail_status = ' have-thumbnail';
}else{
	$thumbnail = '';
	$thumbnail_status = ' no-thumbnail';
}

//タグ
if( !empty( $atts['taglist'] ) && $atts['taglist'] == 'false' ){
}else{
	$taxonomies = get_the_taxonomies();
	if( !empty( $taxonomies ) ){
		$tags .= '<p class="taglist">';
		$count=1;
		foreach ( $taxonomies as $tax => $value ){
		    $tags .= '<span class="taglist-tax taglist-' . $tax . ' tax-order-' . $count . '">';
			$terms = wp_get_object_terms( $post->ID, $tax );
			foreach ( $terms as $term ){
				$tags .= '<a href="' . get_term_link( $term ) . '" class="taglist-term taglist-term-' . esc_html( $term->slug ) . '">' . $term->name . '</a>';
			}
			$tags .= '</span>';
		$count++;
		}
		$tags .= '</p>';
	}
}

//カスタムフィールド
if( !empty( $atts['cf_data'] ) && $atts['cf_data'] == 'true' ){
	if( get_field( 'cf_data_archive' ) ){
		$cf_data_archive = '<div class="cf-data cf-data-archive">' . get_field( 'cf_data_archive' ) . '</div>';
	}else{
		$cf_data_archive = '';
	}
}else{
	$cf_data_archive = '';
}

//「詳しく見る」ボタン
if( !empty( $atts['link_btn'] ) && $atts['link_btn'] == 'true' ){
	$link_btn = '<p>詳しく見る</p>';
}

//WPP順位取得
if( function_exists( 'wpp_get_mostpopular' ) ){
$rank_num = array_search( get_the_ID(), array_column( $rank_data, 'id' ) );
if ( $rank_num !== false ) {
	$ranking = ' ranking ranking-' . ( $rank_num + 1 );
}
}

//編集リンク
if( current_user_can( 'edit_post', get_the_ID() ) ){
	$edit_link = get_option( 'p2_edit_link' );
	$edit_link_url = get_edit_post_link();
	if( $edit_link == 1 ){
	}else{
		$edit_this = '<footer class="entry-meta edit-link-wrap"><span class="edit-link"><a href="' . $edit_link_url . '" target="_blank" rel="noopener">' . __( 'Edit This' ) . '</a></span></footer>';
	}
}

			$sentence .= '<article' . $self_id . 'class="shortcode-article va-css' . $article_flex . $ranking . $article_class . $thumbnail_status . $date_status . $current . '">' . $thumbnail . '<div class="loop-content">' . $avatar . $author_display . '<header class="entry-header">' . $date . '<h2 class="entry-title post-title">' . '<a class="link-shortcode-title' . $link_class . '"' . $link_url . $link_target . '>' . $post_title . '</a>' . '</h2>' . '</header>' . $tags . $excerpt . $cf_data_archive . $link_btn . $edit_this . '</div></article>' . "\n";
			$tags = '';
		}
		$sentence .=  "\n" . '</div>' . $archive_link . "\n" . '</div>' . "\n" . '</div>' . "\n";
	}
	wp_reset_postdata( );
	return $sentence;
}
add_shortcode( 'show_subloop', 'show_subloop' );

オプション

デフォルト

標準投稿、最新記事から4つ、日付、サムネールあり)

「show_subloop」
カスタム投稿
「post_type=”news”」
タクソノミ

「tax=”news_cat”」

ターム

「term=”breaking”」

著者絞り込み

「author=”ユーザー名”」

表示は「ブログ上の表示名」ですが、リンクにはユーザー名が出ちゃうのであまり意味ないか。

アーカイブへのリンクは該当著者の記事一覧になります。

表示数

「show=”1″」=1件

「show=”-1″」=全件

オフセット

「offset=”1″」=2番目に新しい記事

要約

「excerpt=”false”」=要約を出さない

サムネール

「thumbnail=”false”」=アイキャッチ無し

日付

「date=”false”」=日付無し

タグ

「taglist=”false”」=タグ無し

著者表示

「show_author=”true”」=著者表示

アバター

「avatar=”true”」=アバターアイコン出力

タイトル

「title=”ループのタイトル”」=ブロック内にh2タイトルを表示します。

アーカイブへのリンク

「archive_link=”true”」=投稿タイプ名 + 一覧。

taxとtermで絞り込んであれば、タームへのリンクに変わり、「タームラベル + の + 投稿タイプラベル + 一覧」になります。

「archive_link_anker=”一覧:重要なニュース”」= リンクアンカーを置き換えます。

編集リンク

「get_option( ‘p2_edit_link’ )」はグローバル変数によるオプションなので、条件分岐は削除しちゃってください。

 

そのほか、カスタムフィールドやWPP(人気記事リストを作ってくれるプラグイン)などにも対応してますが、コピペでは動かないので割愛。

固定ページでのツリー表示、ページ内遷移用のリンクなども必要だったのでくっつけてますが、普通は要らないか。

 

大分長くなっちゃったので、別ファイルにしてfunctions.phpに読み込んでくださいませ。

そのうちプラグインにしてみよう、、、かな

▼実際に貼り付けると▼

「show_subloop」

標準投稿用のソースをありがたく参考にさせていただきました。

https://gatespace.jp/2012/03/28/show_categoryposts_shortcode/