😐

カスタム投稿で階層構造を実現したいんじゃ

2025/02/19に公開

カスタム投稿で、以下のような階層構造を実現したい方がいらっしゃるかもしれません。

/column/
/column/tokyo/
/column/tokyo/tokyo-jz-trippin/

上からカスタム投稿アーカイブ、カスタムタクソノミーアーカイブ、カスタム投稿詳細です。
これを実現したい場合、プラグインの組み合わせで出来るかも知れませんが、自分はうまくいかなかったので、以下のコードで実現しました。

コード

function column_custom_post_type()
{
    $labels = array(
        'name'          => 'コラム',
        'singular_name' => 'コラム',
        'menu_name'     => 'コラム',
        'edit_item'     => '投稿を編集',
        'view_item'     => '投稿を表示',
    );
    $args = array(
        'labels'        => $labels,
        'public'        => true,
        'has_archive'   => true,
        'menu_position' => 5,
        'show_in_rest'  => true,
        'supports'      => array('title', 'editor', 'thumbnail', 'revisions', 'author'),
        'taxonomies'    => array('area_name')
    );
    register_post_type('column', $args);
    // カスタムタクソノミーを作成
    $args = array(
        'label'     => 'エリア',
        'public'    => true,
        'rewrite'   => ['slug' => 'column'],
        'show_in_rest'  => true,
        'show_ui'   => true,
        'hierarchical' => true
    );
    register_taxonomy('area_name', 'column', $args);
}
add_action('init', 'column_custom_post_type');

/*管理画面のカスタム投稿一覧にタクソノミーを表示*/
function add_column_custom_column_id($area_name, $id)
{
    if ($area_name == 'area_name') {
        echo get_the_term_list($id, 'area_name', '', ', ');
    }
}
add_action('manage_column_posts_custom_column', 'add_column_custom_column_id', 10, 2);
//manage_[カスタム投稿名]_posts_custom_column

/*管理画面のカスタム投稿一覧並び順を変更*/
function column_sort_column($columns)
{
    $columns = array(
        'cb' => '<input type="checkbox" />',
        'title' => 'タイトル',
        'author' => '作成者',
        'area_name' => 'カテゴリー',
        'date' => '日時',
    );
    return $columns;
}
add_filter('manage_column_posts_columns', 'column_sort_column');
//manage_[カスタム投稿名]_posts_custom_column

// リライトルールを修正
function custom_rewrite_rules_for_column($rules)
{
    $new_rules = array(
        'column/([^/]+)/([^/]+)/?$' => 'index.php?post_type=column&name=$matches[2]',
        'column/([^/]+)/?$' => 'index.php?area_name=$matches[1]',
        'column/?$' => 'index.php?post_type=column'
    );
    return $new_rules + $rules;
}
add_filter('rewrite_rules_array', 'custom_rewrite_rules_for_column');


// 新しいクエリ処理を追加
function modify_column_query($query)
{
    if (!is_admin() && $query->is_main_query()) {
        $area_name = get_query_var('area_name');
        $post_name = get_query_var('name');

        if ($post_name && $query->is_singular('column')) {
            $query->set('name', $post_name);
        }
    }
}
add_action('pre_get_posts', 'modify_column_query');

// パーマリンク構造を修正
function custom_column_permalink($url, $post)
{
    if ($post->post_type !== 'column') {
        return $url;
    }

    $terms = get_the_terms($post->ID, 'area_name');
    if (!$terms || is_wp_error($terms)) {
        return $url;
    }

    $term = array_shift($terms);
    return home_url(sprintf('/column/%s/%s/', $term->slug, $post->post_name));
}
add_filter('post_type_link', 'custom_column_permalink', 10, 2);

これで前述のような階層構造が実現出来ると思います。

個人的には、
/column/
/column_area/tokyo/
/column/tokyo-jz-trippin/
で問題ないと考えていますが、こういう要望に基づいて実装した例があったので、共有までです。
こういうところから魔改造が始まるのかもしれないですね

Discussion