【WordPress】カスタム投稿をアルファベット順に一覧表示する方法【コピペOK】

カスタム投稿をアルファベット順に見出し付きで一覧表示する方法をご紹介します。製品一覧などに使用すると便利です。コピペで使えると思います。

  • WORDPRESSで製品一覧を作りたい人

やりたいこと

カスタム投稿タイプで製品的なものを作ってそれを下記みたいに一覧で表示したい。

特徴

  • 記号・数字・アルファベット・その他(漢字・ひらがな・カタカナ)の順で表示
  • 見出しも表示させる
  • ボタンをクリックするとその項目の見出しまで移動する(アンカーリンク)
  • 該当の製品が無い場合、ボタンと見出しは表示しない

設置方法

まずは一覧を表示する固定ページ作成します。ここでは仮に「products」という固定ページを作ることとします。

productsというページを作ってみた

productsというページを作ってみた

固定ページを作ったらテーマファイル「page-products.php」を作成します。

テーマファイルに下記を記述します。下記はカスタム投稿名を「product」とした場合です。そこさえ変えればコピペでいけるはずです。

page-products.php の編集

<!--製品情報取得-->
<?php
$args = array(
  'post_type' => array( 'product' ), //カスタム投稿タイプ'product'を指定
  'orderby' => 'title', //タイトルでソート
  'order' => 'ASC', //昇順
  'posts_per_page' => -1, // 表示させたい記事数、-1だと制限なし
);
$posts = get_posts( $args ); //カスタム投稿タイプ'product'の内容をぶち込む
$allproducts = array();
?>
<!--//製品情報取得-->
<!--準備-->
<?php
$i = 0; //表示件数確認
$j = 0; //漢字表示回数
$k = 0; //記号表示回数
$words = array(); //$wordsという配列を使いまっせ
?>
<!--//準備-->
<!--製品ループ-->
<?php if ( $posts ): foreach ( $posts as $post ): setup_postdata( $post );?>
<?php
$alphac = 0; //アルファベット判定初期化
$kanjic = 0; //漢字判定初期化
$otherc = 0; //その他判定初期化
$no = $i++; //現在の配列ナンバー
$nom = $no - 1; //ひとつ前の配列ナンバー
$fname = mb_substr( the_title( '', '', false ), 0, 1 ); //製品名の一文字目をぶちこむ
$fname = strtoupper( $fname ); //大文字に変換
array_push( $words, $fname ); //配列wordsに入れるよ
$alphac = preg_match( '/[a-zA-Z0-9]/', $fname ); //アルファベット・数字の判定
$kanjic = preg_match( "/([\x{3005}\x{3007}\x{303b}\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}ぁ-んァ-ヶ])(.*|)/u", $fname ); //漢字・ひらがな・カタカナの判定
if ( ( $alphac != 1 )and( $kanjic != 1 ) ) {
  $otherc = 1; //その他のフラグ
}
?>
<?php if ( $words[ $no ] != $words[ $nom ] ) { //ひとつ前の文字と比較して、違う文字ならば処理するよ ?>
<?php
//件数をカウント
if ( $kanjic == 1 ) {
  $kanji_no = $j++;
} elseif ( $otherc == 1 ) {
  $other_no = $k++;
}
?>
<?php if($alphac == 1){ //「アルファベット・数字」ボタンの表示 ?>
<?php array_push( $allproducts, [1,$words[$no],''] );?>
<?php }elseif(($kanjic == 1) and ($kanji_no < 1)){ //漢字・ひらがな・カタカナがある場合「その他」ボタンを表示 ?>
<?php array_push( $allproducts, [1,'その他',''] );?>
<?php }elseif(($otherc == 1) and ($other_no < 1)){ //それ以外の場合「記号」ボタンを表示 ?>
<?php array_push( $allproducts, [1,'記号',''] );?>
<?php } ?>
<?php } ?>
<?php array_push( $allproducts, [0,the_title('','',false),get_permalink()] );?>
<?php endforeach; ?>
<?php endif; wp_reset_postdata(); //クエリのリセット ?>
<!--//ここまで製品ループ-->
<!--ボタン表示-->
<div class="mb-3">
  <?php foreach ( $allproducts as $value ) { ?>
  <?php if($value[0] == 1){ ?>
  <a href="#<?php echo $value[1] ?>" class="btn btn-info mb-2"><?php echo $value[1] ?></a>
  <?php } ?>
  <?php } ?>
</div>
<!--ボタン表示ここまで--> 

<!--見出し・リスト表示-->
<div class="mb-3">
  <?php $i = 0 ?>
  <?php foreach ( $allproducts as $value ) { ?>
  <?php if(($i != 0)and($value[0] == 1)){echo "</ul>";}?>
  <?php if($value[0] == 1){ ?>
  <?php $i = 0 ?>
  <a name="<?php echo $value[1] ?>" id="<?php echo $value[1] ?>"></a>
  <h3><?php echo $value[1] ?></h3>
  <?php }else{ ?>
  <?php if($i == 0){ echo '<ul class="list-group list-group-flush mb-4">';} ?>
  <li class="list-group-item"><a href="<?php echo $value[2] ?>"><?php echo $value[1] ?></a></li>
  <?php $i++ ?>
  <?php } ?>
  <?php } ?>
  </ul>
</div>
<!--見出し・リスト表示ここまで--> 

基本的には上記をコピペすればOKです。classの指定はBootstrap4のレイアウトになっていますので任意で変更してください。

解説

1~12行目

get_posts」でカスタム投稿の内容を取得しています。今回はカスタム投稿タイプ「product」を「タイトル」を「昇順」で「表示数制限なし」に表示する設定にしています。ここをカスタマイズすればソートの方法や表示数の制限等ができます。詳しくは「テンプレートタグ/get posts – WordPress Codex 日本語版 」を参考にしてみてください。

<!--製品情報取得-->
<?php
$args = array(
  'post_type' => array( 'product' ), //カスタム投稿タイプ'product'を指定
  'orderby' => 'title', //タイトルでソート
  'order' => 'ASC', //昇順
  'posts_per_page' => -1, // 表示させたい記事数、-1だと制限なし
);
$posts = get_posts( $args ); //カスタム投稿タイプ'product'の内容をぶち込む
$allproducts = array();
?>
<!--//製品情報取得-->

13~20行目

この行はこれから行う処理の準備です。各変数の初期化を行っています。

<!--準備-->
<?php
$i = 0; //表示件数確認
$j = 0; //漢字表示回数
$k = 0; //記号表示回数
$words = array(); //$wordsという配列を使いまっせ
?>
<!--//準備-->

21~28行目

ここからカスタム投稿の情報をループで出力します。「アルファベット」「漢字・ひらがな・カタカナ」「その他(記号)」を判別するための値の初期化をここで行っています。また、前後の配列を確認するための「$i++」をここで設定しています。

<!--製品ループ-->
<?php if ( $posts ): foreach ( $posts as $post ): setup_postdata( $post );?>
<?php
$alphac = 0; //アルファベット判定初期化
$kanjic = 0; //漢字判定初期化
$otherc = 0; //その他判定初期化
$no = $i++; //現在の配列ナンバー
$nom = $no - 1; //ひとつ前の配列ナンバー

29~37行目

製品名の頭文字を取得する処理です。まずはタイトルの1文字目のみを取得します。次にその文字を大文字に変換し、配列「$words」にぶち込みます。ぶち込んだ頭文字をPHP「preg_match」の正規表現で「アルファベット」「漢字・ひらがな・カタカナ」「その他(記号)」の判別を行っています。

$fname = mb_substr( the_title( '', '', false ), 0, 1 ); //製品名の一文字目をぶちこむ
$fname = strtoupper( $fname ); //大文字に変換
array_push( $words, $fname ); //配列wordsに入れるよ
$alphac = preg_match( '/[a-zA-Z0-9]/', $fname ); //アルファベット・数字の判定
$kanjic = preg_match( "/([\x{3005}\x{3007}\x{303b}\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}ぁ-んァ-ヶ])(.*|)/u", $fname ); //漢字・ひらがな・カタカナの判定
if ( ( $alphac != 1 )and( $kanjic != 1 ) ) {
  $otherc = 1; //その他のフラグ
}
?>

38~58行目

ここではボタンや見出しが重複しないように、「$words[ $no ] 」と「$words[ $nom ]」で文字の比較を行っています。「その他」と「記号」も重複しないように処理しています。さらに製品の情報も配列に格納しています。

<?php if ( $words[ $no ] != $words[ $nom ] ) { //ひとつ前の文字と比較して、違う文字ならば処理するよ ?>
<?php
//件数をカウント
if ( $kanjic == 1 ) {
  $kanji_no = $j++;
} elseif ( $otherc == 1 ) {
  $other_no = $k++;
}
?>
<?php if($alphac == 1){ //「アルファベット・数字」ボタンの表示 ?>
<?php array_push( $allproducts, [1,$words[$no],''] );?>
<?php }elseif(($kanjic == 1) and ($kanji_no < 1)){ //漢字・ひらがな・カタカナがある場合「その他」ボタンを表示 ?>
<?php array_push( $allproducts, [1,'その他',''] );?>
<?php }elseif(($otherc == 1) and ($other_no < 1)){ //それ以外の場合「記号」ボタンを表示 ?>
<?php array_push( $allproducts, [1,'記号',''] );?>
<?php } ?>
<?php } ?>
<?php array_push( $allproducts, [0,the_title('','',false),get_permalink()] );?>
<?php endforeach; ?>
<?php endif; wp_reset_postdata(); //クエリのリセット ?>
<!--//ここまで製品ループ-->

上記命令は「$allproducts」という配列に多次元配列で下記のように製品情報を格納しています。

[【見出し判定】,【見出しor製品名】,【パーマリンクURL】]

見出し判定は格納したデータが「見出し」なら「0」、「製品」なら「1」としています。

これでデータの取得・格納は完了です。続いて出力処理になります。

59~67行目

ボタン表示の箇所です。「foreach」で「$allproducts」の内容を表示しています。見出し部分の項目だけ出力すればよいので「if($value[0] == 1)」で見出し判定が「1」のもののみ表示しています。

<!--ボタン表示-->
<div class="mb-3">
  <?php foreach ( $allproducts as $value ) { ?>
  <?php if($value[0] == 1){ ?>
  <a href="#<?php echo $value[1] ?>" class="btn btn-info mb-2"><?php echo $value[1] ?></a>
  <?php } ?>
  <?php } ?>
</div>
<!--ボタン表示ここまで--> 

68~85行目

見出しとリストの表示です。「if($value[0] == 1)」で見出し判定を行い表示を振り分けています。なんかごちゃごちゃ書いていますが<ul>の表記のためにごちゃってます。

<!--見出し・リスト表示-->
<div class="mb-3">
  <?php $i = 0 ?>
  <?php foreach ( $allproducts as $value ) { ?>
  <?php if(($i != 0)and($value[0] == 1)){echo "</ul>";}?>
  <?php if($value[0] == 1){ ?>
  <?php $i = 0 ?>
  <a name="<?php echo $value[1] ?>" id="<?php echo $value[1] ?>"></a>
  <h3><?php echo $value[1] ?></h3>
  <?php }else{ ?>
  <?php if($i == 0){ echo '<ul class="list-group list-group-flush mb-4">';} ?>
  <li class="list-group-item"><a href="<?php echo $value[2] ?>"><?php echo $value[1] ?></a></li>
  <?php $i++ ?>
  <?php } ?>
  <?php } ?>
  </ul>
</div>
<!--見出し・リスト表示ここまで--> 

以上で解説を終わります。

こんな感じでございやす。bootstrap4お使いの方はほぼコピペでいけると思います。カスタマイズして良きように活用してくださいませ。

 

関連記事