WordPressのカスタム投稿タイプでメンバー紹介ページを作成

先日公開したFrogのサイトは例のごとくWordPressを使って制作しました。ブログで使う「投稿」や、その他の「ページ」とは区別して、これからも増えていくであろうチームメンバーの一覧&詳細ページを、カスタム投稿タイプという機能を使って作成したので手順を公開。企業サイトに従業員一覧ページを用意しているところも多いと思うので、参考になれば幸いです。

目次

  1. 目標 – こんなページを作ります
  2. カスタム投稿タイプとは
  3. カスタム投稿タイプの設定
  4. コンテンツを入力
  5. テーマファイル:個別ページ
  6. テーマファイル:一覧ページ
  7. パーマリンクの設定
  8. コード全文

目標 – こんなページを作ります

Frogのチームメンバーページを実例として紹介します。カスタム投稿タイプを設定するためのWordPressプラグインもありますが、今回はプラグインを使わず設定。プラグインを使わなくても意外と簡単に設定できますよ :)

以下の要素を表示します。

  • 名前
  • 職業
  • 顔写真
  • SNSリンク
  • 概要文
  • 本文(個別ページのみ)

目次へ

カスタム投稿タイプとは

どんなページを作るか、イメージが湧いたところで、タイトルでも使われているカスタム投稿タイプとはなんぞや?という点を解説します。カスタム投稿タイプは、簡単に言うと1つのWordPress内に独自に定義した投稿タイプを追加できる機能です。デフォルトでは以下の5つの投稿タイプがありますが、よく使うのは「投稿」と「ページ」ですね。

  • 投稿 (post)
  • ページ (page)
  • 添付ファイル (attachment)
  • リビジョン (revision)
  • ナビゲーションメニュー (nav_menu)

これ以外に、自分の好みの投稿タイプを作成できるのがカスタム投稿タイプの機能です。投稿タイプを分けることで、タグやカテゴリーで細分化するのではなく、記事の種類自体を別扱いにして管理ができるようになります。今回の例でもブログ投稿とチームメンバーの紹介、そして各ページを区別するためにカスタム投稿タイプを設定します。

custom-post-example

このように管理画面に「メンバー」という項目が追加されるようになります。見た目でもよりわかりやすくなるので、クライアントに提供する際は重宝する機能です。

カスタム投稿タイプに関するより詳しい説明はWordPress公式ドキュメント「投稿タイプ – WordPress Codex」をご覧ください。

カスタム分類

投稿タイプがカスタマイズできるのと同様、タグやカテゴリーといったカスタム分類(タクソノミー)も自由に追加することができます。今回は利用しなかったため解説は省きますが、functions.php にコードを追加することで定義できます。詳しくは「カスタム分類 – WordPress Codex」を参考にしてください。
目次へ

カスタム投稿タイプの設定

functions.php というファイルにカスタム投稿タイプを追加するためのコードを記述して動作を定義します。このコードが少し長くなるので、プログラミングに苦手意識のある方だと少しとっつきにくいかもしれません。ということで、ここに書くためのコードを生成してくれるWordPress Custom Post Type Code Generatorというオンラインジェネレーターを使ってみましょう。

WordPress Custom Post Type Code Generator

ページ上部に書かれている6つのステップに従って必要な項目を入力・選択して埋めていきます。画像クリックで拡大。まず基本設定でカスタム投稿タイプの名前を入力します。一番上の2つのテキストフィールドはダッシュボードで表示するためのものなので日本語でOK。「Post Type Key」は半角英字です。ここでは「team」に設定しました。

余談ですが「メンバー」って見出しなら member というカスタム投稿タイプ名にしろよって思いますよねハイ…。この辺は自分の分かりやすい名前をつけてください。

2. Features では投稿する際に必要となる項目にチェックを入れます。今回は各項目を以下のように使います。

  • Title → 名前
  • Thumbnail → 顔写真
  • Custom Fields → 職業、SNSリンク
  • Excerpt → 概要文
  • WYSIWYG Editor → 本文

Taxonomies(カスタム分類)にチェックを入れればカテゴリーやタグも使えるようになります。

3. Labels ではダッシュボードで表示するための文章を入力します。

4〜6はデフォルトでOK。必要があれば任意で変更してください。後は生成されたコードを functions.php にコピペすれば完了です!

サムネイル画像の設定

上記の設定だけでは顔写真をアップロードするための機能が定義されていないので、以下のコードも追記します。

add_theme_support( 'post-thumbnails', array( 'team' ) );
set_post_thumbnail_size( 150, 150, true );

array で設定したカスタム投稿タイプの「team」を指定して、投稿タイプが「team」の場合にのみサムネイル画像挿入のインターフェースを有効にします。2行目はアップロードされた写真を150x150pxで切り抜く、という設定です。サムネイル画像の設定に関しては「WordPress 2.9 の新機能の投稿サムネイル画像の使い方」がわかりやすいです。ぜひご一読を。

ダッシュボード用のアイコンを追加

アイコンが表示されない

ログインしてダッシュボードで確認してみましょう。新しく「メンバー」という項目ができています!でもよく見ると「メンバー」という見出しにアイコンがついていません。最重要項目ではありませんが、クライアントに納品する場合はこれじゃかっこ悪いですね。そちらも functions.php で設定しましょう。

function add_menu_icons_styles(){
     echo '<style>
          #adminmenu #menu-posts-team div.wp-menu-image:before {
               content: "\f307";
          }
     </style>';
}
add_action( 'admin_head', 'add_menu_icons_styles' );

dashicons

アイコンはDashiconsというアイコンフォントが使われています。別のアイコンに変更するには、Dashiconsのアイコン一覧から好みのものを選択し、上部の「Copy CSS」をクリックすると、そのアイコンのコードが表示されます。上記例の content: "\f307"; の部分をそれと変更してください。
目次へ

コンテンツを入力

こんな感じで入力。必要な人数分を用意します。
目次へ

テーマファイル:個別ページ

続いて入力したコンテンツを表示するため、テーマファイルを作成します。個別ページのファイル名は single-カスタム投稿タイプ名.php となるので、今回は「single-team.php」というファイルを新規作成。基本的には通常のループ処理と同じ書き方でOK。
参考→WordPress オリジナルテーマの作り方 3.0+ ループをコピペする

各項目を表示

各項目は以下のコードをループ内に書いて表示させます。

タイトル(名前)

<?php the_title(); ?>

サムネイル画像(顔写真)

<?php the_post_thumbnail(); ?>

カスタムフィールド(職業、SNSリンク)

<?php echo get_post_meta($post->ID,'メンバー:職業',true); ?>

概要文

<?php the_excerpt(); ?>

本文

<?php the_content(); ?>

目次へ

テーマファイル:一覧ページ

single-team.phpを別名保存し、「archive-team.php」というファイル名にします。これが各チームメンバーの一覧ページです。一覧ページは archive-カスタム投稿タイプ名.php というファイル名になります。

本文を表示する部分の <?php the_content(); ?> を消去し、代わりに個別ページへのリンクボタンを設置。

<a href="<?php the_permalink(); ?>">
     詳しい経歴を見る
</a>

重要な点はループの呼び出し方!通常の

<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>

ではなく、

<?php
     $loop = new WP_Query(array("post_type" => "team"));
     if ( $loop->have_posts() ) : while($loop->have_posts()): $loop->the_post();
?>

に書き換えてコードを使用する必要があります。もちろん「team」の部分は設定したカスタム投稿タイプ名に変更してください。

ループ部分はほとんど同じ内容になるので、別途 loop-team.php を作成し、

<?php get_template_part( 'loop', 'team' ); ?>

で呼び出してもOK。(条件分岐が増えてわかりにくいかなーってことで、今回は解説を割愛…)
目次へ

パーマリンクの設定

上記までで記事はうまく表示されているはずです。しかしパーマリンクの構造を変更することで、より簡潔でわかりやすいURLにすることができます。ダッシュボードの 設定 > パーマリンク設定で「カスタム構造」を選択し、下記の内容に変更します。

/%category%/%postname%/

これで一覧ページは http://example.com/team 、個別ページは http://example.com/team/member-name として表示されるようになります。

ちなみにパーマリンクの設定を変更後、すでに作成しているカスタム投稿のスラッグを変更した際は、このページで何も変更せず「変更を保存」ボタンを押して“空更新”しないと変更が反映されない事があるので注意が必要です
目次へ

コード全文

functions.php 全文

<?php
// カスタム投稿タイプを定義
add_action( 'init', 'register_cpt_team' );

function register_cpt_team() {

    $labels = array(
        'name' => _x( 'メンバー', 'team' ),
        'singular_name' => _x( 'メンバー', 'team' ),
        'add_new' => _x( '新規追加', 'team' ),
        'add_new_item' => _x( '新しいメンバープロフィールを追加', 'team' ),
        'edit_item' => _x( 'メンバープロフィールを編集', 'team' ),
        'new_item' => _x( '新しいメンバー', 'team' ),
        'view_item' => _x( 'メンバープロフィールを見る', 'team' ),
        'search_items' => _x( 'メンバー検索', 'team' ),
        'not_found' => _x( 'プロフィールが見つかりません', 'team' ),
        'not_found_in_trash' => _x( 'ゴミ箱にプロフィールはありません', 'team' ),
        'parent_item_colon' => _x( '親メンバー:', 'team' ),
        'menu_name' => _x( 'メンバー', 'team' ),
    );

    $args = array(
        'labels' => $labels,
        'hierarchical' => true,
        'description' => '経歴紹介とか',
        'supports' => array( 'title', 'editor', 'excerpt', 'thumbnail', 'custom-fields' ),
       
        'public' => true,
        'show_ui' => true,
        'show_in_menu' => true,
       
        'show_in_nav_menus' => true,
        'publicly_queryable' => true,
        'exclude_from_search' => false,
        'has_archive' => true,
        'query_var' => true,
        'can_export' => true,
        'rewrite' => true,
        'capability_type' => 'post'
    );

    register_post_type( 'team', $args );
}

// サムネイル画像を利用
add_theme_support( 'post-thumbnails', array( 'team' ) );
set_post_thumbnail_size( 150, 150, true );

// アイコンを追加
function add_menu_icons_styles(){
     echo '<style>
          #adminmenu #menu-posts-team div.wp-menu-image:before {
               content: "\f307";
          }
     </style>';
}
add_action( 'admin_head', 'add_menu_icons_styles' );
?>

single-team.php 全文

<?php get_header(); ?>
<?php get_sidebar(); ?>    

<div id="main" role="main">
     <div class="page-wrap">
    
     <?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
          <div class="page-title">
               <h1>メンバー紹介 - <?php the_title(); ?></h1>
          </div>
          <!-- /.page-title -->
         
          <article class="container">
               <div class="author row">
                    <div class="col span_3 author-img"><?php the_post_thumbnail(); ?></div>
                    <div class="col span_9">
                         <h2><?php the_title(); ?> <span class="team-title"><?php echo get_post_meta($post->ID,'メンバー:職業',true); ?></span></h2>
                         <p><?php the_excerpt(); ?></p>
                         <p class="author-meta">
                         <?php
                              if(get_post_meta($post->ID,'メンバー:Webサイト',true)){
                                   echo '<a href="'.get_post_meta($post->ID,'メンバー:Webサイト',true).'"><span class="lsf">web</span></a> ';
                              }
                              if(get_post_meta($post->ID,'メンバー:Twitter',true)){
                                   echo '<a href="'.get_post_meta($post->ID,'メンバー:Twitter',true).'"><span class="lsf">twitter</span></a> ';
                              }
                              if(get_post_meta($post->ID,'メンバー:Facebook',true)){
                                   echo '<a href="'.get_post_meta($post->ID,'メンバー:Facebook',true).'"><span class="lsf">facebook</span></a>';
                              }
                         ?>
                         </p>
                    </div>
               </div>
               <!-- /.row -->
              
               <div class="row team-content">
                    <?php the_content(); ?>
               </div>
               <!-- /.row -->
          </article>
          <!-- /.container -->
          <?php endwhile; endif; ?>
     </div>
     <!-- /.page-wrap -->
</div>
<!-- /#main -->

<?php get_footer(); ?>

archive-team.php 全文

<?php get_header(); ?>
<?php get_sidebar(); ?>    

<div id="main" role="main">
     <div class="page-wrap">
          <div class="page-title">
               <h1>メンバー紹介</h1>
          </div>
          <!-- /.page-title -->
         
          <?php
               $loop = new WP_Query(array("post_type" => "team"));
               if ( $loop->have_posts() ) : while($loop->have_posts()): $loop->the_post();
          ?>
          <article class="author container row">
               <div class="col span_3 author-img"><?php the_post_thumbnail(); ?></div>
               <div class="col span_9">
                    <h2><?php the_title(); ?> <span class="team-title"><?php echo get_post_meta($post->ID,'メンバー:職業',true); ?></span></h2>
                    <p><?php the_excerpt(); ?></p>
                    <p class="author-meta">
                    <?php
                         if(get_post_meta($post->ID,'メンバー:Webサイト',true)){
                              echo '<a href="'.get_post_meta($post->ID,'メンバー:Webサイト',true).'"><span class="lsf">web</span></a> ';
                         }
                         if(get_post_meta($post->ID,'メンバー:Twitter',true)){
                              echo '<a href="'.get_post_meta($post->ID,'メンバー:Twitter',true).'"><span class="lsf">twitter</span></a> ';
                         }
                         if(get_post_meta($post->ID,'メンバー:Facebook',true)){
                              echo '<a href="'.get_post_meta($post->ID,'メンバー:Facebook',true).'"><span class="lsf">facebook</span></a>';
                         }
                    ?>
                    </p>
                    <p class="team-more">
                         <a href="<?php the_permalink(); ?>" class="btn blue">
                              詳しい経歴を見る <span class="lsf">right</span>
                         </a>
                    </p>
               </div>
          </article>
          <!-- /.container -->
          <?php endwhile; endif; ?>
         
     </div>
     <!-- /.page-wrap -->
</div>
<!-- /#main -->

<?php get_footer(); ?>

思ったよりも長くなってしまった…。企業サイトやポートフォリオサイトを制作の際に参考にしていただければ幸いです。

目次へ

シェアする

コメント

  • はまだ

    初めまして。
    現在、カスタム投稿タイプによるポートフォリオのようなサイト作成をし、クリエイターボックスを拝見させていただきました。

    見た通りに、やれているはずなのですがうまくいきません。。。

    カスタム投稿タイプの一覧ページをナビゲーションにリンクさせたい場合はheader.phpからカスタム投稿タイプのパーマリンクを貼ればいいのでしょうか。。。
    初心者で、カスタム投稿タイプのページを作るのは初めてなので混乱しています。
    よければご教授願いいたいと思います。
    よろしくお願いいたします。。。

  • はまだ

    申し訳ありません!!!
    できました!!

    記事本当にありがたかったです。。。

    参考になりました。
    ありがとうございました。。

  • 解決できてよかったです!

  • たかぎ

    初めまして、カスタム投稿フィールドで作成したメンバーページに、通常の投稿記事(メンバーに関連した)につけたタグの関連記事を作成する事は出来るでしょうか?

  • カテゴリーやタグは、カスタム投稿タイプと通常の投稿で共有可能です。以下が参考になるかもです。取得したタグを元に関連記事を表示できます!
    WordPressテーマの作り方 » カスタム投稿にカテゴリやタグを追加する http://wordpress.hitsuji.me/categories-for-custom-post-type/
    WordPress › フォーラム » カスタム投稿タイプのタクソノミの使い方について http://ja.forums.wordpress.org/topic/4760

  • たかぎ

    返信がおそくなりすみません。

    ご回答いただきありがとうございます。
    なんとか以下の方法で解決することが出来ました。

    ID , ‘tagid2’ ,true); ?>

  • Pingback: gucci リ抜シ ・ウ・ヤゥ` シ、ーイ()

  • hakama

    はじめまして。

    初心者です。初めてカスタムに手を出しました。

    とても参考になります。ありがとうございます。

    さて、

    >続いて入力したコンテンツを表示するため、テーマファイルを作成します。個別ページのファイル名は single-カスタム投稿タイプ名.php となるので、今回は「single-team.php」というファイルを新規作成。

    とありますが、作成した「single-team.php」は何処に置けば良いのでしょうか?

  • テーマフォルダ内です。single.phpやheader.php等のファイルと同じ階層です!

  • hakama

    子テーマでサイト編集しているのですが、single.php、header.phpとも、親テーマにはあるのですが、子テーマにはありませんでした。親、子、どちらに入れるべきでしょうか?
    /themes/xxxxx/直下にあり
    /themes/xxxxx-child/どこにも見当たらず

  • 子テーマです!

  • hakama

    ありがとうございます!!
    子テーマに入れてみました。
    ところが、上手く表示されてくれません。。。

    元々、teamページをブログ(通常の投稿)で作成してまして、ブログは以下URLでした。

    http://www.xxxxx.com/team/

    それを今回、カスタム投稿にして、カスタム投稿でMichelを登録してみたわけですが、そうなると、http://www.xxxxx.com/team/michelとなるわけですが、これが元々の通常の投稿のURLと被ります。

    なので、通常投稿のmichelをmichel-oldに書き換えました。

    書き換えた後に、http://www.xxxxx.com/team/michelにアクセスすると、なんと勝手に通常投稿にリダイレクトされてしまいます。

    そこで、元々の通常投稿のMichelを下書きに戻したのですが、すると、やはり同じように強制的にmichel-oldにリダイレクトされた上で、Not Foundになります。

    ちなみに、http://www.xxxxx.com/teamにアクセスした所、きっちりとブログの記事一覧画面が出てきました。

    どうすれば良いでしょうか?

  • hakama

    インストール済みのプラグインを停止、有効って感じで、どんどんやっていたら、この問題は解決しました。お騒がせしました。
    次の問題として、テーマ自体のスタイルシートが適用されないという問題にぶちあたりました。これはテーマの問題であって、カスタム投稿の問題ではないですかね?

  • hakama

    結局、プラグイン「Custom Post Type UI」で実現しました。ただ、最初は「カスタム投稿って何?」という状態でしたが、本記事を読むことで、Custom Post Type UIを扱えるだけの知識が身に付きました。本当にありがとうございました。これからもどうぞよろしくお願いします。

  • なかなか返信できずすみませんでした(´ε`;)
    解決できたようでよかったです!これからもよろしくお願いします!

  • Ari Shimooka

    はじめまして。

    カスタム投稿でのユーザー紹介ページの作成、とても参考になりました。
    ありがとうございました。

    少し困っていることがあり、教えていただけるとありがたく質問させて頂きました。
    ここで質問する内容と少しずれているかもしれませんが、ご容赦ください。

    長文で投稿したカスタム投稿をページ分割しようと、

     ①作成したカスタム投稿を利用してページを作成します。
     ②長文の投稿内容であるため、投稿文中に「」を記述
     ③「single-カスタム投稿名.php」ファイルに「wp_link_pages()」を記述

    の作業を行いました。
    上記①から③の作業で、投稿ページを開くと、ナビゲーションのリンク自体は表示されるのですが、
    例えば2ページ目を開こうと表示されたリンクの「2」をクリックすると、ページを開こうとした後、
    「このウェブページにはリダイレクト ループが含まれています」とエラー(?)が出て、2ページ目

    以降のページを表示することが出来ません。
    いろいろ調べてみてはいるのですが、問題を解決できずに困っています。

    ぜひご教授いただきたくコメント投稿させていただきました。
    よろしくお願いいたします。

ニュースレター

Web制作の最新情報やWebクリエイターボックスからのお知らせ、中の人の近況等を定期的にお送りいたします。 ぜひご登録ください!もちろん無料です! :)