【WordPress】投稿でも親子関係をもたせる方法
WordPress

【WordPress】投稿でも親子関係をもたせる方法

デフォルトでは固定ページのみ親子関係を持たせることができますが、投稿でも同様に親子関係を持たせて表示したい場合の設定方法です。functions.phpに記載します。

functions.php

/* 通常投稿に親子関係をもたせる */
function post_add_options( $args, $post_type ) {
  if ( 'post' === $post_type ) {
    $post_labels         = array(
      'name'               => '投稿',
      'singular_name'      => '投稿',
      'menu_name'          => '投稿',
      'name_admin_bar'     => '投稿',
      'add_new'            => '新規追加',
      'add_new_item'       => '新規投稿を追加',
      'new_item'           => '新規投稿',
      'edit_item'          => '投稿の編集',
      'view_item'          => '投稿の表示',
      'all_items'          => 'すべての投稿',
      'search_items'       => '投稿の検索',
      'not_found'          => '投稿が見つかりませんでした。',
      'not_found_in_trash' => 'ゴミ箱に投稿が見つかりませんでした。',
      'attributes'         => '投稿の属性',
    );
    $args['labels']      = $post_labels;
    $args['hierarchical'] = true;
    add_post_type_support( 'post', 'page-attributes' );
  }
  return $args;
}
add_filter( 'register_post_type_args', 'post_add_options', 10, 2 );


加えて、URLをhttps://〇〇.com/[親ページスラッグ]/[子ページスラッグ]と表示する場合には以下をfunctions.phpに追記します。

/* 親投稿のスラッグを取得 */
function get_parent_post_slug($post){
  if (!is_object($post) || !$post->post_parent) {
      return false;
  }
  return get_post($post->post_parent)->post_name;
}

/* get_sample_permalinkのfilterフック */
add_filter('get_sample_permalink', function ($permalink, $post_id, $title, $name, $post) {
  if ($post->post_type != 'post' || !$post->post_parent) {
      return $permalink;
  }
  $template_permalink = current($permalink);
  $replacement_permalink = next($permalink);
  $postname_string = '/%postname%/';
  $parent_slug = get_parent_post_slug($post);
  $altered_template_with_parent_slug = '/' . $parent_slug . $postname_string;
  $new_template = str_replace($postname_string, $altered_template_with_parent_slug, $template_permalink);
  $new_permalink = [$new_template, $replacement_permalink];

  return $new_permalink;
}, 99, 5);

/* post_linkのfilterフック */
add_filter('post_link', function ($post_link, $post, $leavename) {
  if ($post->post_type != 'post' || !$post->post_parent) {
      return $post_link;
  }
  $parent_slug = get_parent_post_slug($post);
  $new_post_link = str_replace($post->post_name, $parent_slug . '/' . $post->post_name, $post_link);

  return $new_post_link;
}, 99, 3);

/* pre_get_postsのactionフック */
add_action('pre_get_posts', function ($query) {
  global $wpdb, $wp_query;
  $original_query = $query;
  $uri = $_SERVER['REQUEST_URI'];

  if ($query->is_main_query() && !is_admin()) {
      $basename = basename($uri);
      $test_query = sprintf("select * from $wpdb->posts where post_type = '%s' and post_name = '%s';", 'post', $basename);
      $result = $wpdb->get_results($test_query);

      if (!($post = current($result)) || !$post->post_parent) {
          return $original_query;
      }

      $parent_slug = get_parent_post_slug($post);
      $hierarchal_slug = $parent_slug . '/' . $post->post_name;

      if (!stristr($uri, $hierarchal_slug)) {
          return $original_query;
      }

      $query->query_vars['post_type'] = ['post'];
      $query->is_home = false;
      $query->is_page = true;
      $query->is_single = true;
      $query->queried_object_id = $post->ID;
      $query->set('page_id', $post->ID);

      return $query;
  }
}, 1);


注意点として、パーマリンク設定は/%postname%/とすること。

~~ END ~~