オレオレrelated posts

Pocket

WordPressにて、

  • カスタマイズしたテーマを利用し、テイストを崩したくない
  • Related Postsを表示したいけど、表示するpostをWP管理画面で指定したい
  • 表示するpostを指定しない場合は、カテゴリーから

という要望があり、Related postsを簡単に設定する方法を考える。

使うプラグイン

  • CMB2 ( https://wordpress.org/plugins/cmb2/ )
  • CMB2 Attached Posts Field ( https://github.com/CMB2/cmb2-attached-posts )

使い方

1. 上記のプラグインを有効にする

2. CMB2 Attached Post Field のexampleを参考に、こんな感じで functions.php に

function cmb2_attached_posts_field_metaboxes_post() {
    $example_meta = new_cmb2_box( array(
        'id'           => 'cmb2_attached_posts_field',
        'title'        => 'Related Articles',
        'object_types' => array( 'post' ), // Post type
        'context'      => 'normal',
        'priority'     => 'high',
        'show_names'   => false, // Show field names on the left
    ) );
    $example_meta->add_field( array(
        'name'    => 'Attached Posts',
        'desc'    => 'Drag posts from the left column to the right column to attach them to this page.<br />You may rearrange the order of the posts in the right column by dragging and dropping.',
        'id'      => 'attached_posts',
        'type'    => 'custom_attached_posts',
        'column'  => true, // Output in the admin post-listing as a custom column. https://github.com/CMB2/CMB2/wiki/Field-Parameters#column
        'options' => array(
            // 'show_thumbnails' => true, // Show thumbnails on the left
            'filter_boxes'    => true, // Show a text box for filtering the results
            'query_args'      => array(
                'posts_per_page' => 10,
                'post_type'      => 'post',
            ), // override the get_posts args
        ),
    ) );
}



function cmb2_attached_posts_field_metaboxes_package() {
    $example_meta = new_cmb2_box( array(
        'id'           => 'cmb2_attached_packages_field',
        'title'        => 'Related Packages',
        'object_types' => array( 'package' ), // Post type
        'context'      => 'normal',
        'priority'     => 'high',
        'show_names'   => false, // Show field names on the left
    ) );
    $example_meta->add_field( array(
        'name'    => 'Attached Packages',
        'desc'    => 'Drag posts from the left column to the right column to attach them to this page.<br />You may rearrange the order of the posts in the right column by dragging and dropping.',
        'id'      => 'attached_packages',
        'type'    => 'custom_attached_posts',
        'column'  => true, // Output in the admin post-listing as a custom column. https://github.com/CMB2/CMB2/wiki/Field-Parameters#column
        'options' => array(
            'show_thumbnails' => true, // Show thumbnails on the left
            'filter_boxes'    => true, // Show a text box for filtering the results
            'query_args'      => array(
                'posts_per_page' => 10,
                'post_type'      => 'package',
            ), // override the get_posts args
        ),
    ) );
}

add_action( 'cmb2_init', 'cmb2_attached_posts_field_metaboxes_post' );
add_action( 'cmb2_init', 'cmb2_attached_posts_field_metaboxes_package' );

post typeはcustom post typeでも使えるようにしておくと便利か。

このプラグインでは、idで指定したmeta_name (上記の例だと attached_posts, attached_packages)に、serializeされたarrayで post idが保存される。

3. 表示するところ(例えばsingle.php)に、

<?php

    if( $post->post_type == 'post'){
        $numberposts = 3;
        $section_name = 'Related Posts';
    } elseif( $post->post_type == 'package'){
        $numberposts = 3;
        $section_name = 'Related Packages';

    }
?>
<h1><?php echo $section_name; ?></h1>
                                                        
    <div class="items">
<?php
        // get related posts
        $attached_posts = get_post_meta( get_the_ID(), 'attached_posts', true );

        if( is_array( $attached_posts ) && sizeof( $attached_posts) > 0 ){

            $args = array(
                'post_type' => $post->post_type,
                'post__in' => $attached_posts,
                'orderby' => 'rand',
                'numberposts' => $numberposts
            );
        }
        else {
            // get related posts by category
            $cats = get_the_category();

            $args = array(
                'post_type' => $post->post_type,
                'post__not_in' => array( get_the_ID() ),
                'orderby' => 'rand',
                'posts_per_page' => $numberposts,
                'cat'     => $cats[0]->term_id,

            );


        }

        $the_query = new WP_Query( $args );

        while ( $the_query->have_posts() ) : 

            $the_query->the_post(); 

            if( $post->post_type == 'post'){
                get_template_part('content', 'post_box');

            }
            elseif( $post->post_type =='package'){
                get_template_part('content', 'package_box');
            }


        endwhile;
        wp_reset_postdata();
?>
    </div>

のようにしておく。contentはtemplate参照。

the_content hookを使うとrecursiveになっちゃう場合があるのでオススメしない。別途hookを定義すると良いかも。