カスタムフィールドで複数のPDF表示とグループ機能(Toolset Types編)

カスタムフィールドで複数画像の表示 (Toolset Types編)は、基本的な使い方や画像の表示についてでしたが、今回は複数のPDFの表示方法やグループ機能などについても触れてみたいと思います。

カスタムフィールド登録でのPDFを表示するコード

投稿フィールドの設定方法は画像の設定と同じようにできますので省きます。コードの内容で画像表示の時と異なるのは、altの代わりにタイトルを設定したり、追加で「ファイルサイズ」表示の設定をすることくらいです。

PDFの表示

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<?php
    $pdfs = get_post_meta($post->ID, 'wpcf-pdf', false);
    $judge = array_filter($pdfs);
    if($judge) {
        foreach ($pdfs as $pdf) {
            $query = "SELECT ID FROM $wpdb->posts WHERE guid = %s";
            $prepared = $wpdb->prepare($query, $pdf);
            $attachment_id = $wpdb->get_var($prepared);
            $url = wp_get_attachment_url($attachment_id);
            $pdf_title = get_the_title($attachment_id);
            $path = str_replace(esc_url(home_url('/'))."wp/", ABSPATH, $url);
            if(is_file($path)){
                $size = size_format(filesize($path));
            }
            $out = '<a class="link pdf" target="_blank" href="'.$url.'">'.$pdf_title.'('.$size.')</a>';
            echo $out;
        }
    }
...
?>

ファイルサイズの取得

WordPress メディアのファイルサイズを表示する方法 – by Takumi Hirashimaを参考にさせていただきました。

グループ機能

続いて、グループ機能についてです。ちょっとクセがあります。

ポストリレーションシップ

Toolset Typesではカスタムフィールドをグループ化する機能はなく、その代わりに「ポストリレーションシップ」という、投稿をグループ化する機能があります。この機能で親の投稿に複数の子の投稿を紐付けてカスタムフィールドグループのように管理します。親の投稿にはカスタムフィールドが直接紐付けされているわけではないので、ループの処理も二重になります。

グループの設定

投稿関係(親/子)を設定します。各投稿タイプの編集ページ下部に設定欄があります。子の投稿には別途、カスタムフィールドを設定しておきます。

グループの設定はToolset Types:カスタムフィールドグループの繰り返し – WordPress Noteがわかりやすいです。

親子投稿の手順

初回投稿の方法は下記の手順が良さそうです。

  • あらかじめ親の投稿を「公開」で投稿。ポストリレーション用カスタムフィールドで作業はせずに子の投稿一覧へ移動。
  • 子の投稿を作成。カスタムフィールドに情報を入力後、親の投稿を選択して投稿。

Post Type Switcherとの併用時は注意

Post Type Switcherと併用した場合、最初に親の投稿を「非公開」や「下書き」で投稿しておいて、後から「公開」にすると子の投稿が親へ移動(投稿タイプを親の投稿タイプに変更)してしまいます。

子のカスタム投稿表示の考え方

2つのカスタム投稿を用意して、下記のようにループを二重で設定することになります。

  1. 親のループ開始
  2. 親の投稿ごとに情報を取得して表示
  3. 親の投稿ごとに紐づけられた子のループ開始
  4. 子の投稿ごとに情報を取得して表示
  5. 子のループ終了
  6. 子用に上書きされていた$postをリセット
  7. 親のループ終了
  8. 親用に上書きされていた$postをリセット

6が要らないような気もします(いまだに、Wordpressの仕組みを完全に理解できていないです)。

実際のコード

親の投稿に紐づけられた子の投稿のクエリ条件を設定するコードは下記のようになります。

子の投稿のクエリ条件設定(WP_Query)

<?php
    // クエリの条件
    $child_target_post = ‘子のカスタム投稿のスラッグ’
    $child_post_count = -1
    // クエリの設定
    $child_args = array(
        'post_type' => $child_target_post, // 表示する投稿タイプ
        'paged' => $paged,
        'meta_query' => array(array('key' => '_wpcf_belongs_xxxxxxxxx_id', 'value' => get_the_ID())), // toolsetの独自指定。親の投稿IDを取得する。
        'post_status' => 'publish',
        'posts_per_page' => $child_post_count, // 表示するページ数
        'order' => 'DESC' // 並び順
    );
    $child_query = new WP_Query($child_args);
?>

Toolset Typesでは親の投稿IDを取得する場合、「post_parent」ではなく、「meta_query」で指定します。

Please note the key argument _wpcf_belongs_writer_id in the meta_query property. The writer part is the slug of our parent post type. If you were listing the children posts of a “House” post type, you would use _wpcf_belongs_house_id.

公式サイトのとおり、「_wpcf_belongs_xxxxxxxxx_id」の「xxxxxxxxx」に親の投稿スラッグを入れて設定します。この記述がないと、親の投稿ごとに紐づけられた子の投稿を表示させるつもりが、親の投稿ごとに子のすべての投稿が表示されるので注意が必要です。続いて二重サブループのコードです。

親と子の二重サブループ(PDF表示の場合)

<?php
    // クエリの条件
    $target_post = ‘親のカスタム投稿のスラッグ’
    $post_count = -1
    // クエリの設定
    $paged = get_query_var('paged') ? get_query_var('paged') : 1;
    $args = array(
        'post_type' => array($target_post), // 表示する投稿タイプ
        'paged' => $paged, // ページ番号
        'post_status' => 'publish’, // 投稿の状態
        'posts_per_page' => $post_count, // 表示するページ数
        'order' => 'DESC' // 並び順
    );
    $my_query = new WP_Query($args);
?>
// 親のループ開始
<?php if ($my_query->have_posts() ) : while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
…
// 親の情報を表示
<h3><?php the_title(); ?></h3>
// 子の情報を表示
<div class=“child”>
    (子の投稿のクエリ条件設定)
    // 子のループ開始
    <?php if ($child_query->have_posts() ) : while ( $child_query->have_posts() ) : $child_query->the_post();
    (PDFの表示)
    // 子のループ終了
    <?php endwhile; else: ?>
    <p>申し訳ありません。投稿はまだありません。</p>
    <?php endif; ?>
    // 子用に上書きされていた$postをリセット
    <?php wp_reset_postdata(); ?>
</div>
// 親のループ終了
<?php endwhile; else: ?>
<p>申し訳ありません。投稿はまだありません。</p>
<?php endif; ?>
// 親用に上書きされていた$postをリセット
<?php wp_reset_postdata(); ?>

管理画面メニュー内の表示順(menu_position)

管理画面の左メニューにおけるカスタム投稿の表示順はfunction.phpで設定するときと同様に行えます。既存の項目を選択することで、その項目のすぐ下にカスタム投稿名が表示されます。

設定方法

  1. Toolset > Post Types からカスタム投稿を選択
  2. 設定ページの右部にある「右記以降のAdmin Menu 位置: 」下のセレクトメニューをクリック
  3. 既存の項目を選択

親子投稿が多くなって調整が必要になったときにどうぞ。なお、「Show number of entries on “At a Glance” admin widget.」と書かれたチェック項目がありますが、これはメニュー表示の順番設定用ではなく、ダッシュボードでの表示の有無を設定するためのものです。

menu_position

さいごに

ポストリーレーションが大げさに感じる場合はSmart Custom Fieldsがオススメです。

デフォルトでグループ機能も使えて管理もしやすく、さらにカスタムフィールドの値もシリアライズされません。開発者の方に感謝です。

以上です。