WordPress 3.0 カスタム投稿タイプの試用でカスタムメニューと子テーマも理解

WordPress は、3.0 になって新たに公開された豊富な機能により、利用が一段と面白くなってきた。それらの機能は、今まで築き上げたサイト構築の手法の変更を迫っているようにも感じる。制作者側は大変だろうが、今後 WordPress 3.0 ならではのサイトが出現してくると思われるので楽しみだ。

さて、WordPress で扱う記事(ページの内容)は、それまでは静的な記事は「ページ」、動的な記事は「投稿」というような使い分けが専らだったと思う。ブログとして使うのであれば、話題によりカテゴリーで分類できる。タグもキーワードとして利用できる。

では、産業界で商品や製品を分類して WordPress で扱うにはどうしたらいいだろうか?

あるいは、記事によって文や画像のレイアウトを変えて表現するにはどうしたらいいだろうか?

それぞれ自前の解決方法を構築していると思うが、新しい機能「カスタム投稿タイプ」は、上手く利用すれば今までよりも効率的に開発を進める事ができる機能、ではないかと思う。

子テーマ

実践での利用シーンは思い付いていないが、テーマに少し手を加えて使ってみたいとき、今回のように動作を試してみたい時、「これは便利だ!」と感心した。

それは、テーマに含まれているテンプレートなどのオリジナルファイルに手を加えることなく、追加したり変更したい部分だけを抽出してやればいいからである。

使い方は簡単、子テーマのディレクトリ「wp-content/themes/子テーマ名」を作成し、「style.css」のテーマ情報ヘッダ部分で、「Template」項目に親テーマ名を書き加えて保存すればよい。スタイル本体は親テーマから import する。

@charset "utf-8";
/*
Theme Name: kid2010
Description: WordPress のデフォルトテーマ twentyten の子テーマ。
Author: オレ
Template: twentyten
*/

@import url('../twentyten/style.css');

#site-title a {
	color: #009900;
}

後は管理画面の「外観-テーマ」で、子テーマを選択すればよい。ページを表示したとき変更が分かるように、タイトルを緑色にしている。

参考ページ:子テーマ

カスタム投稿タイプ

WordPress に保存される記事は、post_type としてブログの「post」以外に「page」、それらの書替え履歴となる「revision」、画像などのメディアに関する情報を持つ「attachment」、そしてカスタムメニューに関する情報を持つ「nav_menu_item」がシステムで用意されたものである。

カスタム投稿タイプは、これらに独自のタイプを追加して利用する機能である。保存できる情報は投稿やページと同様であるが、項目をタイトルと内容のみというように、極小まで絞る事ができる。

さて、実際に独自の投稿タイプを使えるようにするため、テーマの「functions.php」にフックを利用して登録する。ここで先ほどの子テーマを利用して、子テーマディレクトリに以下の登録とフック関数を「functions.php」に用意する。

<?php
add_action('init', 'mobile_custom_init');
function mobile_custom_init() {
	$labels = array(
		'name' => _x('Mobiles', 'post type general name'),
		'singular_name' => _x('Mobile', 'post type singular name'),
		'add_new' => _x('Add New', 'mobile'),
		'add_new_item' => __('Add New Mobile'),
	);

	$args = array(
		'labels' => $labels,
		'public' => true,
		'supports' => array('title', 'editor', 'author', 'thumbnail'),
		'rewrite' => array('slug' => 'mob'),
	);
	register_post_type('mobile', $args);
}
?>

「register_post_type()」によって、「mobile」という独自のタイプを追加した。管理画面を開いて左側のメニューを見ると、追加した「mobile」に関するメニューが追加される。「Add New」で記事を登録してみよう。

上のパラメータの「rewrite」であるが、この記事を表示するパーマリンクにおいて「http://example.com/mob/スラッグ名」とするための指定だ。「rewrite」の指定が無いと「タイプ名/スラッグ名」となる。

参考ページ:Custom Post Types

さて、独自タイプで入力した記事の表示である。Twentyten のテンプレートそのままでは表示できない。テーマを作る際、テンプレートにループなどいろいろ指定するが、独自タイプの記事を表示するにも同様に指定しなければならない。

そこで簡単に表示するため、メニューから表示するようにして見よう。

カスタムメニューの表示

サイト上でフレキシブルなメニュー構成が作れるため、この機能は大変ありがたい。そのメニュー構成を作るには、「管理画面-外観」でメニューを選択すればよい。

Twentyten では、「main」というメニューが1つあり、ホーム、紹介、が既に登録されている。この後ろに、独自タイプで登録した記事のタイトル「モバイルページ」を追加してみる。

メニューを選択すると、カスタム投稿で登録したページが選択できる小窓が表示されているので、追加したい記事のタイトルにあるチェックボックスをチェックして「メニューに追加」すればよい。

次にこのメニュー構成をサイトで表示するため、「header.php」を書き換える。Twentyten のディレクトリから、子ディレクトリにコピーし、73行目の「wp_nav_menu()」に「main」というメニューを使うように、「’menu’=>’main’」パラメータを追加すればよい。

	<?php /* Our navigation menu.  If one isn't filled out, wp_nav_menu falls back to wp_page_menu.  The menu assiged to the primary position is the one used.  If none is assigned, the menu with the lowest ID is used.  */ ?>
	<?php wp_nav_menu( array('menu' => 'main', 'container_class' => 'menu-header', 'theme_location' => 'primary' ) ); ?>

これでメニューを設定できた。サイトを表示してメニューを選択すれば、登録したカスタム投稿の記事を表示する事ができる。

メニューのリンク URI を見ると、「rewrite」で指定したスラグが使われて「mob/スラグ名」となっているのが確認できる。

サイトにおけるメニューは、ヘッダー部やフッター部、そしてサイドバーなどあらゆるところにナビゲーションを置く事が多い。なので WordPress 3.0 のメニュー機能は、サイト構築者に大変便利な機能を提供してくれたと思う。

参考ページ:テンプレートタグ/wp_nav_menu

どの機能も簡単に試してみる事ができ、体感を得る事ができた。カスタム投稿タイプの利用は、大きな広がりがあるように思う。そして実際に利用するには、WordPress の CMS としての機能をもっと理解し、充実した作りにしないといけない事も確かであろう。

カスタムポストタイプの参考:WordPress3.0beta1でカスタム投稿タイプを具体的に使う

WordPress Ver. 3.0.1


  • トラックバック 停止中
  • コメント (16)
  1. 東京都在住ですが山梨県人です。同県のよしみで(^^)教えていただければ幸いです。
    カスタムメニューの項目に、固定ページや、カテゴリーアーカイブを設定しています。
    特に、カテゴリーアーカイブページでは、カスタムメニューのトップ階層に出現するのは
    親カテゴリーとして、親をマウスダウンすると、下の方に子カテゴリーが階層的に
    表示されるような設定としています。

    そこで教えて頂きたいことがあります。
    wp_get_nav_menu_items()関数を使って、メニューのトップ階層から下の階層に
    向かって設定されているカテゴリーアーカイブ関連ページに関するデータを得たいのですが、
    どのようにしたらよいでしょうか?得たい情報は、カスタムメニューに入っている
    カテゴリーのidまたはスラッグ、そして(管理画面のカスタムメニューで任意の順に
    並べた後ドラッグあんどドロップして設定した階層に従って)カスタムメニューで階層
    表示される順番、に関するデータです。

    なぜ、このようなことをしているのかというと、親カテゴリーから見たカテゴリー
    アーカイブページを作ろうとして、カテゴリー
    をリストアップする際、カテゴリーid順やスラッグ順ではなく、「タスタムメニューで
    任意に並べた結果」の順にリストアップされるようにしたいのです。
    こうすれば、順番をカスタムメニューで変更しても、その結果が、カテゴリーアーカイブ
    にも反映されるからです。

    どうかお知恵を拝借させてください。よろしくお願いします。

  2. @pyon-yon
    ご質問に関して、的を外してましたらご容赦ください。

    pyon-yonさんが欲しいデータは、ディレクトリ(フォルダ)のようなカスタムメニューで定義したカテゴリアーカイブの階層構造、と解釈しました。それを、wp_get_nav_menu_items()関数でどのように取得するか?と言うことだと思います。

    wp_get_nav_menu_items()を使うと、そのメニューアイテムに含まれるメニューアイテムの配列が取得できるので、再帰的に呼び出す関数を使えばいいと思います。関数の骨格は次のようになると思います。

    function get_menu_recursively($navi) {
    	$children = wp_get_nav_menu_items($navi->ID);
    	$menus = array();
    	if ($children) {
    		foreach ($children as $child) {
    			$menus[] = array(
    				'menu' => $child,
    				'children' => get_menu_recursively($child);
    			}
    		}
    	}
    	return $menus;
    }
    

    これでツリー構造が取得できると思います。メニューの並びは配列の順番で、メニューの情報は ‘menu’キー、子メニューがなければ ‘children’キーは空配列となります。

  3. 早速にご教示をありがとうございます。
    まず確認ですが、
    ・8行目の「;」は必要でしょうか?
    ・9行目の「 }」は「 )」でよいですね?

    その上で早速、(このような使い方でよいどうかわからなかったのですが)以下のように
    実施して見ました。

    <?php
    $navi = ‘global-nav';
    続けて、いただいたコード
    ?>

    そして表示させると、次のエラーとなりました。
    Parse error: syntax error, unexpected ‘}’ in D:\Program Files\xampp\htdocs\wordpress-v3\wp-content\themes\third-style\category-12.php on line 53

    「 }」を一つ削除してみましたが、別のところを指摘されてしまいます。
    お気づきのことがあれば、再度よろしくお願いします。

  4. エラーは、
    $menus[] = array(
    ‘menu’ => $child,
    ‘children’ => get_menu_recursively($child)
    );
    として、出ないようになりました。

    <?php
    $navi = ‘global-nav’;
    続けて、いただいたコード
    ?>
    以外に、何か設定が必要なのでしょうね?

  5. @pyon-yon さん
    文法上の誤りがあり失礼しました。修正はpyon-yonさんの通りで、
    8行目行末の「;」は削除して下さい。9行目「}」は「);」で配列を閉じて下さい。

    再帰関数への引数はメニューオブジェクトになります。ですから、予め「wp_get_nav_menu_items()」で取得したものを渡す必要があります。あるいは「wp_get_nav_menu_object()」が利用できるかもしれません。

    サンプルコードは再帰関数と階層データのツリーの作り方を示したもので、メニューの関数や動作について確認してません。調べてみますので少しお時間を下さい。

  6. ありがとうございます。
    ちなみに経過をお伝えいますと、
    $navi = ‘global-nav’;
    としていたところを、
    $navi = wp_get_nav_menu_items(‘global-nav’);
    として試していますが、エラーも出ませんが、出力はホワイトページの状態です。

  7. 「wp_get_nav_menu_items()」の戻り値を調べてみたところ、勘違いをしていました。上のサンプルコードは破棄して下さい m(_ _)m。

    「wp_get_nav_menu_items()」の戻り値は、指定したメニューとそのメニュー以下全てを、メニューオブジェクトの配列で返してきます。

    例えばカテゴリー「Cat1~Cat7」があり、階層が次のようになっているとします。

    Cat1
        Cat3
        Cat7
            Cat6
            Cat4
        Cat2
            Cat5
    

    このとき「wp_get_nav_menu_items()」の戻り値であるオブジェクト配列は、

    [0]=>Cat1
    [1]=>Cat3
    [2]=>Cat7
    [3]=>Cat6
    [4]=>Cat4
    [5]=>Cat2
    [6]=>Cat5
    

    となっています。メニューオブジェクトのプロパティには、「ID, menu_item_parent, url, title」などがあります。階層の情報は、「menu_item_parent」を見れば親となるIDの値か、もしくはトップレベルなら「0」が入ってます。

    後は処理したい内容に合わせて、この配列を参照してプログラムを書く事になると思います。

    なお戻り値は「var_dump($navi)」で表示確認できます。ブラウザの「ソース」表示を利用すれば、データは見易くなります。

  8. 見方がわかってきました。奮闘してみます。
    今後ともよろしくお願いします。ありがとうございました。

  9. 「wp_get_nav_menu_items()」関数の戻り値をしっかり確認していれば、遠回りせず回答できたのに、と反省してます。
    プログラミング頑張って下さい。

  10. 昨日はありがとうございました。
    恥ずかしながら、基本的なことで行き詰まりました。
    $menu_items = wp_get_nav_menu_items(‘global-navi’);
    foreach($menu_items as $menu) :
    if ($menu->menu_order = 2 || $menu->menu_order = 3 || $menu->menu_order = 4 || $menu->menu_order = 5 || $menu->menu_order = 6 ) {
    echo ‘[title] ‘. $menu->title . ‘ (ID: ‘. $menu->object_id . ‘)';
    }
    などとして、所定のメニューにマウスオーバーした際に表示されるサブメニュー項目を
    表示させてみました。(キーmenu_order)が表示される順番を保持しているので、これを
    使うのが汎用性が高いと思ったからです。
    しかし、結果は、所定のメニューだけでなく、カスタムメニューに入っている全項目が
    表示されてしまうようです。
    (キーmenu_item_parent)では、if ($menu->menu_item_parent == 317)
    などとして絞って表示することができるのですが、
    (キーmenu_order)では、$menu->menu_order = 5 などとしても無視されるようです。menu_item_parentはstringですが、menu_order はINT みたいです。

    簡単なことだと思うのですが、うまく行きません。条件指定が効くようにするには
    どのようにしたらよいのか、教えて下されば幸いです。

    よろしくお願いします。

  11. ソースの確認ですが、if文の比較演算子では「==」を利用しないといけませんが、「=」代入になっていませんか?

    ところで、<pre>タグが利用できますので、ソースを記述する際ご利用下さい。

  12. 解決しました。あわてておりました。
    これまでのご指導で、思っていることができそうです。
    大変助かりました。ありがとうございました。

    今後ともどうぞよろしくお願いします。

  13. 解決して良かったですね。

    なおご質問された場合は、何が誤りで、どのように訂正して解決することができたか明示していただけると、質問を受けた側、また閲覧している人にも親切かと思いますので、今後よろしくお願いします。

  14. 大変失礼いたしました。まとめさせていただきます。
     カスタムメニューにおいて、「Cat1」項目がカテゴリーの親となっており、
    サブメニューを以下のように設定しました。
    Cat1
    Cat3
    Cat7
    Cat6
    Cat4
    Cat2
    Cat5
     この場合において、「Cat1」項目をクリックして表示させる親カテゴリーの
    アーカイブが表示するカテゴリー順を、カスタムメニューに合わせ、マニューを
    変更しても、アーカイブのカテゴリー順も自動的に変更されるようにすることが
    課題でした。

     そこで、「wp_get_nav_menu_items()」関数を調べて、以下のような骨子で
    コードを作成し、ほぼ実現の見通しが得られました。

    menu_order == 2 || $menu->menu_order == 3 || $menu->menu_order == 4 || $menu->menu_order == 5 || $menu->menu_order == 6 ) {
    echo ‘[title] ‘. $menu->title . ‘ (ID: ‘. $menu->object_id . ‘)';
    }
    endforeach;
    //var_dump($menu_items);
    ?>

    キーである「menu_order」に、カスタムメニューに設定した表示順が保持されて
    いるため、カテゴリーアーカイブでなくても、固定ページ等の階層メニューの
    場合にもうまく使えるのではないか、と思います。
     なお、当初は、条件検索で「menu_order = 2」としたり、失敗しましたが、
    「menu_order == 2」と修正し、所期のとおり、カテゴリー名を期待通りの順で
    抽出することができました。
     今後は、メニューの順番でリストされるカテゴリーごとに、投稿記事タイトル、
    概要、等を合わせて表示できる「親カテゴリーアーカイブ」に仕上げたいと思って
    おります。

     以上、よろしくお願いいたします。

  15. プレタグを使ったのですが、どっかでサニタイズされてしまいました。
    すみません。

  16. まとめをいただきありがとうございます。催促したつもりはなかったのですが、どうも済みませんでした。

    自分もアーカイブページでタイトル一覧表を作ってみたいと思っていたので、今回の件は参考になりました。

    その他サイトマップも自動で作れるし、応用ができそうです。

    今後ともよろしくお願いします。

コメント 停止中