PublishPress SeriesプラグインでカスタムREST APIエンドポイントを作成する方法

この記事では、WordPressのPublishPress Seriesプラグインを利用してカスタムREST APIエンドポイントを作成し、シリーズのデータやその関連投稿を取得する方法を解説します。この方法を使用すれば、シリーズ機能を他のアプリケーションやカスタムテーマに簡単に統合できます。

注意:プラグインをアップデートすると編集したコードが上書きされるのでChild themeを使用することをお勧めします。

このカスタムAPIでできること

  1. 全シリーズを取得
    エンドポイント /publishpress/v1/series/ を利用して、すべてのシリーズと関連する投稿データを取得します。
  2. スラッグで特定のシリーズを取得
    /publishpress/v1/series/{slug} で、特定のスラッグ(シリーズの識別子)を持つシリーズデータと投稿を取得します。
  3. IDで特定のシリーズを取得
    /publishpress/v1/series/{id} を利用して、シリーズのIDに基づいてシリーズデータを取得します。


実装手順

作業に入る前に必ずファイルのバックアップをとっておくようにしましょう。

WordPressのアドミンページにログインして、Apperance → Theme File Editor → functions.php ファイルを選択します。

カスタムREST APIエンドポイントの登録

/publishpress/v1/series/ エンドポイントで呼び出される関数です。この関数は、シリーズごとの投稿データを返します。

function get_series_list() {
    $terms = get_terms(array(
        'taxonomy' => 'series',
        'hide_empty' => false,
    ));

    if (is_wp_error($terms) || empty($terms)) {
        return new WP_Error('no_series', 'No series found', array('status' => 404));
    }

    $response = array();

    foreach ($terms as $term) {
        $args = array(
            'post_type' => 'post',
            'tax_query' => array(
                array(
                    'taxonomy' => 'series',
                    'field'    => 'id',
                    'terms'    => $term->term_id,
                ),
            ),
            'posts_per_page' => -1,
            'orderby' => 'menu_order',
            'order' => 'ASC',
        );

        $posts = get_posts($args);
        $post_details = array();

        foreach ($posts as $index => $post) {
            $post_details[] = array(
                'id' => $post->ID,
                'title' => $post->post_title,
                'slug' => $post->post_name,
                'current_part' => $index + 1,
            );
        }

        $response[] = array(
            'term_id'     => $term->term_id,
            'name'        => $term->name,
            'slug'        => $term->slug,
            'description' => $term->description,
            'post_count'  => $term->count,
            'posts'       => $post_details,
        );
    }

    return rest_ensure_response($response);
}

全シリーズと関連投稿を取得するコールバック関数

/publishpress/v1/series/ エンドポイントで呼び出される関数です。この関数は、シリーズごとの投稿データを返します。

function get_series_list() {
    $terms = get_terms(array(
        'taxonomy' => 'series',
        'hide_empty' => false,
    ));

    if (is_wp_error($terms) || empty($terms)) {
        return new WP_Error('no_series', 'No series found', array('status' => 404));
    }

    $response = array();

    foreach ($terms as $term) {
        $args = array(
            'post_type' => 'post',
            'tax_query' => array(
                array(
                    'taxonomy' => 'series',
                    'field'    => 'id',
                    'terms'    => $term->term_id,
                ),
            ),
            'posts_per_page' => -1,
            'orderby' => 'menu_order',
            'order' => 'ASC',
        );

        $posts = get_posts($args);
        $post_details = array();

        foreach ($posts as $index => $post) {
            $post_details[] = array(
                'id' => $post->ID,
                'title' => $post->post_title,
                'slug' => $post->post_name,
                'current_part' => $index + 1,
            );
        }

        $response[] = array(
            'term_id'     => $term->term_id,
            'name'        => $term->name,
            'slug'        => $term->slug,
            'description' => $term->description,
            'post_count'  => $term->count,
            'posts'       => $post_details,
        );
    }

    return rest_ensure_response($response);
}

スラッグで特定のシリーズを取得

/publishpress/v1/series/{slug} エンドポイントで特定のシリーズデータを取得する関数です。

function custom_series_endpoint($data) {
    $slug = $data['slug'];
    $series_term = get_term_by('slug', $slug, 'series');

    if (!$series_term) {
        return new WP_Error('no_series', 'Series not found', array('status' => 404));
    }

    $args = array(
        'post_type' => 'post',
        'tax_query' => array(
            array(
                'taxonomy' => 'series',
                'field'    => 'slug',
                'terms'    => $slug,
            ),
        ),
        'posts_per_page' => -1,
        'orderby' => 'menu_order',
        'order' => 'ASC',
    );

    $posts = get_posts($args);
    $post_details = array();

    foreach ($posts as $index => $post) {
        $post_details[] = array(
            'id' => $post->ID,
            'title' => $post->post_title,
            'slug' => $post->post_name,
            'current_part' => $index + 1,
        );
    }

    $response = array(
        'series' => array(
            'term_id'     => $series_term->term_id,
            'name'        => $series_term->name,
            'slug'        => $series_term->slug,
            'description' => $series_term->description,
        ),
        'posts' => $post_details,
    );

    return rest_ensure_response($response);
}

上記のすべてのコードを一つにまとめました。

// Register custom REST API routes for PublishPress Series
function register_publishpress_series_rest_routes() {
    // Endpoint to get all series
    register_rest_route('publishpress/v1', '/series/', array(
        'methods' => 'GET',
        'callback' => 'get_series_list',
    ));

    // Endpoint to get series by slug
    register_rest_route('publishpress/v1', '/series/(?P<slug>[a-zA-Z0-9_-]+)', array(
        'methods' => 'GET',
        'callback' => 'custom_series_endpoint',
    ));
	
 	register_rest_route('publishpress/v1', '/series/(?P<id>\d+)', array(
        'methods' => 'GET',
        'callback' => 'custom_series_by_id_endpoint',
        'args' => array(
            'id' => array(
                'validate_callback' => function ($param) {
                    return is_numeric($param);
                },
            ),
        ),
    ));
	
}

// Callback to fetch all series and their associated post details
if (!function_exists('get_series_list')) {
    function get_series_list() {
        $terms = get_terms(array(
            'taxonomy' => 'series',
            'hide_empty' => false,
        ));

        if (is_wp_error($terms) || empty($terms)) {
            return new WP_Error('no_series', 'No series found', array('status' => 404));
        }

        $response = array();

        foreach ($terms as $term) {
            $args = array(
                'post_type' => 'post',
                'tax_query' => array(
                    array(
                        'taxonomy' => 'series',
                        'field'    => 'id',
                        'terms'    => $term->term_id,
                    ),
                ),
                'posts_per_page' => -1,
                'orderby' => 'menu_order', // Use 'menu_order' for custom ordering in series
                'order' => 'ASC',
            );

            $posts = get_posts($args);
            $post_details = array();

            foreach ($posts as $index => $post) {
                $post_details[] = array(
                    'id' => $post->ID,
                    'title' => $post->post_title,
                    'slug' => $post->post_name,
                    'current_part' => $index + 1, // 1-based index for the order
                );
            }

//             $response[$term->term_id] = array(
//                 'series_ID'   => $term->term_id,
//                 'checked'     => false, // Assuming checked is some default value
//                 'ser_name'    => $term->name,
//                 'slug'        => $term->slug,  // This is the slug of the series
//             );
			
            $response[] = array(
                'term_id'     => $term->term_id,
                'name'        => $term->name,
                'slug'        => $term->slug,
                'description' => $term->description,
                'post_count'  => $term->count,
                'term_order'  => $term->term_order,
                'posts'       => $post_details,
            );
        }

        return rest_ensure_response($response);
    }
}

// Callback function for the /series/{slug} endpoint
if (!function_exists('custom_series_endpoint')) {
    function custom_series_endpoint($data) {
        $slug = $data['slug'];

        $series_term = get_term_by('slug', $slug, 'series');

        if (!$series_term) {
            return new WP_Error('no_series', 'Series not found', array('status' => 404));
        }

        $args = array(
            'post_type' => 'post',
            'tax_query' => array(
                array(
                    'taxonomy' => 'series',
                    'field'    => 'slug',
                    'terms'    => $slug,
                ),
            ),
            'posts_per_page' => -1,
            'orderby' => 'menu_order', // Use 'menu_order' for custom ordering in series
            'order' => 'ASC',
        );

        $posts = get_posts($args);
        $post_details = array();

        foreach ($posts as $index => $post) {
            $post_details[] = array(
                'id' => $post->ID,
                'title' => $post->post_title,
                'slug' => $post->post_name,
                'current_part' => $index + 1, // 1-based index for the order
            );
        }

        $response = array(
            'series' => array(
                'term_id'     => $series_term->term_id,
                'name'        => $series_term->name,
                'slug'        => $series_term->slug,
                'description' => $series_term->description,
                'post_count'  => $series_term->count,
                'term_order'  => $series_term->term_order,
            ),
            'posts' => $post_details,
        );

        return rest_ensure_response($response);
    }
}

// Callback function for the /series/{id} endpoint
if (!function_exists('custom_series_by_id_endpoint')) {
    function custom_series_by_id_endpoint($data) {
        global $wpdb;

        $id = $data['id'];

        // Fetch the series data directly from the database
        $series_data = $wpdb->get_row($wpdb->prepare("
            SELECT t.term_id, t.name 
            FROM {$wpdb->terms} t 
            JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id 
            WHERE t.term_id = %d AND tt.taxonomy = %s
        ", $id, 'series'));

        if (!$series_data) {
            return new WP_Error('no_series', 'Series not found', array('status' => 404));
        }

        $response = array(
            'series_ID' => $series_data->term_id,
            'ser_name'  => $series_data->name,
        );

        return rest_ensure_response($response);
    }
}

// Hook to register custom API routes
add_action('rest_api_init', 'register_publishpress_series_rest_routes');

Leave a Comment