先頭固定記事の出力に四苦八苦して安パイに流れたお話Posted by:喜多 真輝央
みなさんこんにちは。
インスパイアの喜多です。
今回はWordpressの先頭固定について、
意外とネットで検索しても情報が出てこなかった記憶があるのでブログにまとめさせていただきます。
やりたかったこと
〇複数の投稿のフィードを同じページ内に配置
〇運用時の利便性を優先するためそれぞれ同一の投稿タイプを使用し、カテゴリによってどのフィードに表示されるかを分ける
〇記事の先頭固定を有効化(複数記事を先頭固定記事として指定することもあり)
〇ユーザー側で記事表示件数を変えられるようにする(HTMLでの操作希望)
〇上記条件を満たしながら複数フィードの投稿の最大表示件数を同じにする
困ったこと
普通に先頭固定記事を出力するだけならいくらでも情報はあったのですが、
同じ投稿タイプを使っていてカテゴリごとに別のフィードで出力、という要件のせいで上手くいきませんでした。
従来であれば先に先頭固定記事だけ出力して、あとから通常の記事を出力するだけだったのですが、
例えばカテゴリーAには先頭固定記事があるけどカテゴリーBには固定記事がない場合や、
カテゴリーAは固定記事が7件でカテゴリーBは固定記事が2件普通の記事が2件、カテゴリーCは固定記事は無しで普通の記事が7件で最大5件表示というような状況もあり、
一つの投稿タイプの中で複数の条件に対応させる必要があるためテンプレート的な記述ではうまくいかないようでした。
実装したこと
ユーザー側で表示件数を変更できるよう、引数ありのショートコードを作成。
基本的にはカテゴリーごと(フィードごとに)所属する固定記事の件数をカウントし、
そこから想像できる限りのいろんなパターンを想定して、それぞれの状況で対応が出来るよう条件分岐を設定。
詳細は割愛いたしますが、大まかな流れはこんな感じです。
/* ------------------------------------------------------------------------------ 先頭固定対応ショートコード ------------------------------------------------------------------------------ */ function yattemitaKansu($atts){ //表示件数と対象カテゴリーを引数として指定 extract( shortcode_atts( array( "num" => '5', //指定が無ければ5件表示をデフォルトに "cat" => '' ), $atts ) ); //先頭固定記事の出力準備 $stickyArticle = get_option('sticky_posts'); $the_query = new WP_Query(array( 'post_type' => 'post', 'posts_per_page' => $num, 'cat' => $cat, 'post__in' => $stickyArticle, //先頭固定記事のみ抽出 )); $retHtml = '<dl class="feed-wrap">'; //記事の出力 if (!empty( $stickyArticle )): //先頭固定記事が存在するなら $stickyNum = $the_query->found_posts; //先頭固定記事の件数取得 while ($the_query->have_posts()) : $the_query->the_post(); $retHtml.= '<dd class="feed-item sticked-item">'; $retHtml.= '<a href="'.get_permalink().'"><span>'.get_post_time('Y.m.d').'</span>'.get_the_title("","",false).'</a></dd>'; endwhile; else: //先頭固定記事が1件も存在しない場合 $stickyNum = 0; //先頭固定記事の件数を指定 endif; wp_reset_postdata(); $normalNum = $num - $stickyNum; //先頭固定じゃない記事の表示件数 = 全体の表示件数 - 先頭固定記事の件数 $the_query = new WP_Query(array( 'post_type' => 'post', 'posts_per_page' => $normalNum, 'cat' => $cat, 'post__not_in' => $stickyArticle, //先頭固定記事を除外 )); if ($normalNum > 0): //先頭固定じゃない記事の表示件数 = 全体の表示件数 - 先頭固定記事の件数 if ($the_query->have_posts()) : while ($the_query->have_posts()) : $the_query->the_post(); $retHtml .= '<dd class="list-item">'; $retHtml.= '<a href="'.get_permalink().'"><span>'.get_post_time('Y.m.d').'</span>'.get_the_title("","",false).'</a></dd>'; endwhile; $retHtml .= '</dl>'; endif; endif; wp_reset_postdata(); return $retHtml; } add_shortcode("syutsuryoku", "yattemitaKansu");
元の記述はユーザー名等の記載が入っていたため、今回ブログにまとめるようにちょっと記述を変更しております。
もしかしたらしょうもないエラーをはいてしまっているかもしれません。
基本的には$the_query->found_posts;
を使用して各カテゴリーごとの先頭固定記事の件数を数えて、
N = N1 – N2
N1:ショートコード側で設定した記事の表示件数
N2:各カテゴリごとの先頭固定記事の件数
という計算でNを決めて、N > 0の時だけ固定じゃない記事を出力するようにしています。
投稿タイプ内に固定記事が1件も無い時は'post__in' => $stickyArticle,
が効かず全記事が出力されてしまうので、
固定記事の出力部分はif (!empty( $stickyArticle )):
で固定記事が存在しているときだけ出力するようにしています。
この部分、if文を使わずに上記のNのところの調整でいけないかな~とNがマイナスの時の条件等をあれやこれやしていたのですが、
記事の総件数が最大表示件数を下回っている場合に重複出力されてしまうエラーなどがあり、
解決するには新たな変数N3:カテゴリ内の記事の総数が必要になりそうでかえって長くなってしまいそうだったので、
大人しくif文に頼りました。
何か負けた気がしてしまうんですよね、こういうの。
改めて完成したコードを見てみると、やっぱり対して特別なことは何もしていないんですよね。
ただ、意外と検索してすぐ出てくるサンプルコードとかだと解消できないエラーを乗り越えてくれているのでありがたいです。
この記述ももっと煮詰められそうではあるのですが、時間がないのでこのままになっています。
多分またこの記述だと乗り越えられない要件とかが出てくると思うので、
その時にあわせて改修したいですね。
本日はこのくらいで。
それでは、また。
P.S
元々ラーメンが好きなのですが、
最近は特に鶏チャーシューにはまっています。
鶏むね肉を低温熟成したタイプの鶏チャーシューがとても好きで、
鶏チャーシュー丼なんて食べられた日には喜び舞い上がります。
ただ、そんな鶏チャーシューを提供しているお店でも、
チャーシュー丼はジューシーな豚バラを使用しているスタンスなお店もあり、
実際に注文してみるまでは分からないハラハラドキドキ感もあります。
ちなみに今のところの戦績では、
20件回って目当てのチャーシュー丼は1件だけでした。
的中率0.5%なら良心的ですね、マラソンします。