3.0 以前
昔は本気でこんなことしてたんだねぇ、ほぇー。と懐かしむことになるであろう現在のありがちなツクリを例に挙げてみよう。
ブログを始めたえびちゃんは、お仕事で撮影したヘアスタイルをブログに載せたいとナジミの wper にオネダリしてみた。もちろんブログ(日記)の一投稿としてではなく、別途ヘアスタイルカタログ的なものを望んでいる。さらには「ロング,ウェーブ」などの情報も付けたいし「お気に入り度」も欲しいと言う。
ボクが欲しいのはキミだけなのに、とかグジグジ思ってはいけない。欲しがったら負けだ。オマエを選んでやってもいいぜ?くらいの気持ちで臨むのがよろしい。そんなわけで、例えキミが wpist であっても 3.0 以前では以下のようにするしか無かった。
- 投稿のカテゴリーに「ヘアスタイル」を追加。
- ヘアスタイルを投稿する時は「ヘアスタイル」カテゴリーを選択。
- 「ロング,ウェーブ」はタグを利用。
- 「お気に入り度」はカスタムフィールドを利用。
こうするしか、無かったんだ。しかしそれはキミの都合、そして WordPress 3.0 以前の都合です。えびちゃんは「なんでヘアスタイルが投稿なのよ!なんで日記書くときにお気に入り度とか出てくんのよ!バッカじゃないの?!」とこっちの苦労も考えず好きなこと言いやがります。
ですが、おっしゃることはごもっともなのです。作り手の都合を使う側に押し付けてはいけません。「投稿を新規追加してカテゴリーのヘアスタイルにチェックを入れて投稿のタグにヘアスタイル関連タグを入力してカスタムフィールドの名前からお気に入り度を選択して値に数値を入れて更新ボタンをクリックして...」なんて呪文を唱える方がイカれてるんです。エンジニアでもない人にヘルプ読めとか言う方が何もわかっとらんのです。DIGA の字幕の ON/OFF の仕方がワケわからんぞまったく。
各種デザイナー&デベロッパーの皆さんは、使う人が何も説明されなくても自然と使えてしまう、のがベストなのだと気づきましょう。
3.0 ならこんな風
※以降の内容は beta1 を元に説明しておりますので、正式リリースでは事情が変わるかもしれません。なんてことは今後ともイチイチ書かないのでその辺はよきにはからってください。
で、3.0 ならどうなるのかと言いますと。
- 投稿,ページと同レベルで「ヘアスタイル」を扱える。
- 「ヘアスタイル」を編集,新規追加できる。
- 「ヘアスタイル」に専用の「ロング,ウェーブ」的分類ができる。
- 「ヘアスタイル」に専用の「お気に入り度」を追加できる。
見た方が早いですね。まずは「ヘアスタイル(Hair Styles)」の一覧表示画面です。
おぉぉ、イカしてますね。この一覧表示の各カラムも自由にデザインできますので色々夢が膨らみます。なお「ヘアスタイルの分類」はこの「ヘアスタイル(Hair Style)」専用のタクソノミーです。カスタムタクソノミーの記事で言ってたカスタム投稿タイプとの絡み がこれなんですねー。では次に「ヘアスタイル(Hair Style)」の編集画面。
すばらしい。通常の「投稿の編集」で表示されるメカメカしたメタボックス群もありませんね。これなら使い方をイチイチえびちゃんに説明しなくてもわかってくれます。グダグダ言わずにこのようにあっさり鮮やかに対応するのが男なのさ。
カスタム投稿タイプのおかげでより自由度が高くなっているのに、使う人にも作る人にも優しくなっているのは流石です。3.0 以前の中途半端な実装については不問といたしましょう。やっててよかった WordPress。やはりオレの目に狂いは無いのだぜ。
コード
以下を functions.php に追加すれば OK。もちろん WordPress 3.0 beta1 以降でお試しください。テーマは Twenty Ten 0.7 をご使用です。見ればわかる内容なので説明は割愛するぜ。わかんねーよ、という方はその旨コメントにてお知らせいただければそこそこ丁寧にご回答いたします。
add_action('init', 'my_custom_stuff');
function my_custom_stuff(){
register_post_type(
'hairstyle',
array(
'label' => __('Hair Styles'),
'singular_label' => __('Hair Style'),
'public' => true,
'show_ui' => true,
'capability_type' => 'post',
'hierarchical' => false,
'rewrite' => false,
'query_var' => false,
'supports' => array(
'title',
'editor',
'thumbnail'
),
'register_meta_box_cb' => 'my_hairstyle_meta_box'
)
);
register_taxonomy(
'hairstyletag', /* もうちょっとマシなタクソノミー名を考えよう */
'hairstyle', /* どの post type で使うかを指定 */
array(
'hierarchical' => false,
'update_count_callback' => '_update_post_term_count',
'label' => 'ヘアスタイルの分類',
'singular_label' => 'ヘアスタイルの分類',
'public' => true,
'show_ui' => true
)
);
}
//
function my_hairstyle_meta_box($post){
add_meta_box('my_hairstyle_meta', 'お気に入り度よ!', 'my_hairstyle_meta_html', 'hairstyle', 'normal', 'high');
}
function my_hairstyle_meta_html($post, $box){
$rating = get_post_meta($post->ID, 'rating', true);
echo wp_nonce_field('my_hairstyle_meta', 'my_meta_nonce');
echo 'このヘアスタイルは... ';
echo '<input type="radio" name="rating" value="めっちゃ好き"' .('めっちゃ好き' == $rating ? ' checked="checked"' : ''). '>めっちゃ好き ';
echo '<input type="radio" name="rating" value="嫌い!"' .('嫌い!' == $rating ? ' checked="checked"' : ''). '>嫌い! ';
echo '<input type="radio" name="rating" value="フツー"' .('フツー' == $rating ? ' checked="checked"' : ''). '>フツー';
}
add_action('save_post', 'my_hairstyle_meta_update');
function my_hairstyle_meta_update($post_id){
if(!wp_verify_nonce( $_POST['my_meta_nonce'], 'my_hairstyle_meta'))
return $post_id;
if(defined('DOING_AUTOSAVE') && DOING_AUTOSAVE)
return $post_id;
if('hairstyle' == $_POST['post_type']){
if(!current_user_can('edit_post', $post_id))
return $post_id;
}else{
return $post_id;
}
$rating = $_POST['rating'];
if($rating == '')
delete_post_meta($post_id, 'rating');
else
update_post_meta($post_id, 'rating', $rating);
}
//
add_filter('manage_edit-hairstyle_columns', 'my_hairstyle_columns');
function my_hairstyle_columns($columns){
$columns = array(
'cb' => '<input type="checkbox"/>',
'title' => 'スタイル名',
'image' => '画像',
'tag' => '分類',
'rating' => 'お気に入り度',
'date' => '日付'
);
return $columns;
}
//
add_action('manage_posts_custom_column', 'my_hairstyle_column');
function my_hairstyle_column($column){
global $post;
if('image' == $column) the_post_thumbnail(array(64, 64), 'class=featured-image');
elseif ("tag" == $column) the_terms(0, 'hairstyletag');
elseif ("rating" == $column) echo get_post_meta($post->ID, 'rating', true);
}
register_post_type:カスタム投稿タイプの登録
えびちゃん好みのカスタム投稿タイプを追加するのがこのファンクションです。詳細は Codex:関数リファレンス/register post type をご覧ください。とは言ってもやっぱりめんどくさがって見ない人がいらっしゃるに違いないので、ご丁寧に説明いたします。Codex と 3.0beta1 のソースで食い違いがある部分はソースの内容を書いておきます。
書き方:
<?php register_post_type($post_type, $args) ?>
$post_type:文字列,必須
カスタム投稿タイプの名前を指定します。
$args:配列,任意
以下のパラメータを指定します。
パラメータ:
label:文字列,任意,デフォルト= $post_type 値
カスタム投稿タイプの管理メニュー表示名として使用されます。
英語なら複数形で。i18n を考慮して __('my-types') のように指定すると良い。
singular_label:文字列,任意,デフォルト= $label 値
新規追加、編集のページで表示されるカスタム投稿タイプ名。i18n を考慮のこと。
description:文字列,任意,デフォルト無し
カスタム投稿タイプの概要。使わないはず。
public:bool,任意,デフォルト=false
カスタム投稿タイプが管理画面で表示される(ユーザに使ってもらう用)か否(裏で使う用)か。
publicly_queryable:bool,任意,デフォルト=public 値
通常のクエリに含むか否か。とは言うものの true でも index.php で出てこないぞ。
exclude_from_search:bool,重要,デフォルト=!public 値
検索結果から除くか否か。
show_ui:bool,任意,デフォルト=public 値
管理メニュー&画面を自動で表示するか否か。
capability_type:文字列,任意,デフォルト='post'
読み書き削除に適用される権限
以降、権限パラメータは通常の投稿と同じで良いなら未指定(デフォルト)で OK。
カスタム投稿タイプ独自の権限を作るなら、これに例えばカスタム投稿タイプ名を指定して、
各種 Role に edit_hairstyle とかなんとかを追加していけば良い。
詳しくは Codex:ユーザーの種類と権限
edit_cap:文字列,任意,デフォルト="edit_$capability_type"='edit_post'
このカスタム投稿タイプに属する記事の編集権限名。
edit_type_cap:文字列,任意,デフォルト= 'edit_' . $capability_type . 's'='edit_posts'
このカスタム投稿タイプの一覧画面での編集権限名。
edit_others_cap:文字列,任意,デフォルト= 'edit_others_' . $capability_type . 's'='edit_others_posts'
他のユーザの作成した記事の編集権限名。
publish_others_cap:文字列,任意,デフォルト= 'publish_' . $capability_type . 's'='publish_posts'
記事の公開権限名。
read_cap:文字列,任意,デフォルト= 'read_' . $capability_type . 's'='readt_post'
記事を読む権限名。
delete_cap:文字列,任意,デフォルト= 'delete_' . $capability_type . 's'='delete_posts'
記事の削除権限名。
hierarchical:bool,任意,デフォルト=false
ページのように階層有り(true)とするか、投稿のように階層無し(false)とするか。
supports:配列,任意,デフォルト=なし
カスタム投稿タイプの編集画面で表示するメタボックスを
add_post_type_support() を使う代わりに、登録時に指定する。
'title' = タイトル欄
'editor' = 本文欄
'author' = 作成者欄
'thumbnail' = 投稿サムネイル/Featured Image 欄
'excerpts' = 抜粋欄
'trackbacks' = トラックバック/ピンバック欄
'custom-fields' = カスタムフィールド欄
'comments' = コメント欄
'revisions' = リビジョン
'page-attributes' (parent, template, and menu order) = ページの属性欄
※デフォルト/未指定の場合は title & editor が自動で設定される。
何かを指定さえすれば、title や editor 無しにもできる。
register_meta_box_cb:文字列(関数名),任意,デフォルト無し
編集画面のメタボックス設定時コールバック。
remove_meta_box() とか add_meta_box() はこのコールバックで行いましょう。
taxonomies:タクソノミー名(文字列)の配列,任意,デフォルト無し
カスタム投稿タイプに関連づけたタクソノミーは別途
register_taxonomy() や register_taxonomy_for_object_type() で登録する方が良い。
これは、すでに登録済のタクソノミーをこのカスタム投稿タイプで使う場合に指定。
menu_postition:文字列,任意,デフォルト=null=一番下
管理メニュー上での表示順位。3.0beta1 では未実装。
menu_icon:文字列,任意,デフォルト=null=投稿のアイコン
管理メニュー画面で使用されるアイコンのURL。3.0beta1 では未実装。
permalink_epmask:文字列,任意,デフォルト=EP_NONE
パーマリンクの何かマスク。気にしなくて OK。
rewrite:配列,任意:デフォルト=true
※パーマリンク設定がデフォルトでない場合に有効。
パーマリンク設定に従ってリンクを書き換えるか否か。
false=http://example.com/?post_type=hairstyle&p=123
true=http://example.com/hairstyle/わんこ風
array('slug' => 'hair-styles')=スラッグを変更=http://example.com/hair-styles/わんこ風
'with_front' - defaults to true よくわからん。
query_var:bool,任意,デフォルト=true
※パーマリンク設定がデフォルトの場合に URL が以下のように変わります。
false=http://example.com/?post_type=hairstyle&p=123
true=http://example.com/?hairstyle=わんこ風
_builtin:bool,使わないこと,デフォルト=false
コア組み込みの投稿タイプ(true)かカスタム投稿タイプ(false)か。
__edit_link:bool,使わないこと,デフォルト='post.php?post=%d'
記事を編集する際のリンク。
最低限指定すべきパラメータは public。あとは label, supports, register_meta_box_cb, taxonomies くらいですね。publicly_queryable=true (public=true)なら通常のブログ記事一覧表示に出てくるはずなんですが、カスタム投稿タイプの記事は出てきませんでした(Twenty Ten 0.7)。眠いからか?とりあえず以下のようにすると、カスタム投稿タイプの記事一覧を表示することはできます。
query_posts('post_type=hairstyle');
今回のタイトルは「使う」でしたが、実際は「作る」まででしたね。早朝なので眠いです。もう寝ます。
カスタム投稿タイプだからできるこんなこと
- 「臨時休業」カスタム投稿タイプで本文と休日だけを入力してもらうと、information の記事として表示しつつ営業日カレンダーに反映。
- 飲食店で「スタッフブログ」の他に「お知らせ」「メニュー」「スタッフ」「クーポン」をカスタム投稿タイプとして追加。カテゴリから解放される!タグ的タクソノミーがカスタム投稿タイプ別に作れる!
他にもえぇっと、あのホラいっぱいあるよカスタム投稿タイプで幸せになれることが。wpxtreme ではアナタのアイデアを募集しています。コメントにてドシドシご応募ください。ドシドシって擬態語?
動作確認バージョン
- WordPress 3.0 beta1

いつもいつも、おいしいご馳走記事ありがとうございます。おいしく頂きます。
カスタマイズ抜きだとあっさりし過ぎて物足りないので食後にプリンをいただきなう!
カスタムタクソノミーが増えたら投稿画面がごっちゃになるな、と思ったら…
なるほどこうなるんですね。Photoshopの表示設定みたいなかんじ。
いろいろ便利な3.0が待ち遠しい。
実は 3.0 の本当の目玉は CS5 との統合です。うそです。
どうも、はじめまして、みみすけと申します。
新米wordpress使用者です。
大変有意義な記事ありがとうございます。
実はブログ立ち上げ中でEvent Calendarなるプラグイン
で記事の主題をカレンダーに表示できないか
頭を抱えていたところ、このブログに巡り会いました。
ファンクションに機能追加する記事を参考にして
独自に作り始めようかと思ったりしていますが
wordpress 3.0ではさらに入力等
カスタマイズできるのかもしれないですね
たいへん勉強になります。
お役に立てれば光栄です。
ガンガン勉強していずれは WordPress を背負って立つ存在になってくださいね!
丁寧かつウィットに富んだ解説ありがとうございます。
WP3.0-RC2にてテスト中です。
参考にさせていただきました。
カスタム投稿のタイトルの日本語の場合、単一ページのURLがすごいことになりませんか?
スラッグ名をアルファベットで指定してやれば、短くできますが。
あっさり味の/%category%/%post_id%.htmlな感じにできるとありがたいのですが。
正式リリース版でなんとかならないですかね・・・?
はじめまして。
最近wordpressをまたさわりだして、コードをいただきつつ勉強させてもらってます!ありがとうございます!
カスタムフィールドをラジオボタン・テキストフィールド・テキストエリアといくつかカスタム投稿タイプ内で表示したいのですが、下記のコードのように並べれば問題ないですか?
お手数ですが、もろもろご相談させて頂きたいと思ってます!
よろしくお願いいたします!
function my_hairstyle_meta_html($post, $box){
$rating = get_post_meta($post->ID, ‘rating’, true);
echo wp_nonce_field(‘my_hairstyle_meta’, ‘my_meta_nonce’);
//——-ラジオボタン
echo ‘おススメ度’;
echo ‘★★★ ’;
echo ‘★★ ’;
echo ‘★’;
echo”.$meta_box['description'].”;
//——-テキストフィールド
echo ‘おススメ度’;
echo ”;//テキストフィールド
echo’aaaa’;
}
未検証ですけどこんな感じでどうでしょう。
radio:
echo ‘オススメ度 ’;
echo ‘<input type=”radio” name=”rating” value=”★★★”‘ .(‘★★★’ == $rating ? ‘ checked=”checked”‘ : ”). ‘>★★★ ’;
echo ‘<input type=”radio” name=”rating” value=”★★”‘ .(‘★★’ == $rating ? ‘ checked=”checked”‘ : ”). ‘>★★ ’;
echo ‘<input type=”radio” name=”rating” value=”★”‘ .(‘★’ == $rating ? ‘ checked=”checked”‘ : ”). ‘>★ ’;
text:
echo ‘オススメ度 ’;
echo ‘<input type=”text” size=”40″ value=”" name=”rating”>’;
はじめまして。septemと申します。
カスタム投稿タイプを利用しようと、検索をしていましたら
こちらに辿り着きました。分かりやすく纏まっていて非常に助かりました。
早速、導入しようと思い立ち実装している最中なのですが、一番最初で壁にぶつかりました…
もし以下内容に関して、解決策をお尻でしたらアドバイスをいただけないでしょうか。
各カスタム投稿の記事一覧ページを作成しようと思いまして、
ページ機能にて作成したページに、「query_posts(‘post_type=***’)」(***はカスタム投稿タイプの名前)と
記事ループと前後ページナビゲーションを記述したページテンプレートを割り当てられました。
表示したところ、最新n件は表示されたのですが、
前後ナビにて次ページへ移動したところ404のテンプレートが表示されてしまいました。
(URLの形式としては「http://example.com/***/page/2/」となっていました)
query_postsの引数のパラメータの先頭に「$query_string」を追加、というのも試しましたがこちらも表示されずでした。
考えてみればページ機能なので前後移動はできないよなぁと思いつつ、
さすがにカテゴリや月別アーカイブなどの体裁が用意できないことはないだろう…と思ったのでお伺いした次第です。
現在は、query_postsにshowposts=-1を追加して1ページで完結していますが記事数も多く悩んでおります。
お忙しい所恐縮ですが、どうぞよろしくおねがいします!
先日、質問させていただいたseptemです。
上記の件ですが、知人と話し合いまして無事解決いたしました。
コメント欄を汚してしまいすみませんでした!
それでは失礼いたします。
夏休みの宿題にしようと思っていたところ、、解決されたようでナニヨリです◎
どう解決されたかコッソリ教えていただくとコメント欄がキラキラしてきますので、よろしくネッ