私的WPテーマ(テンプレート)作成まとめ

デザインのセンスはなく、画像処理ソフトもほとんど使えない人間ですが、テンプレートは自作を続けています。MT/XOOPSからの移行に際して、テンプレートは内製するという伝統を継承すべく、テーマを自作しました。

テーマ作成に当たっては、プラグインを使わないで実現できる機能は、可能な限りテーマで実現することに努めています。プラグインで代替できるものについては、その点について注釈していきます。

ここでは、今回テーマの作成に際して得た知見について、備忘録的にまとめておきたいと思います。

なお、基本的にPHPがわからない人なので、条件分岐などはかなりベタな記述になっていると思います。PHPについては当てずっぽうなところも多いので要注意。一応機能はしてますが。

基本情報

基本中の基本、テンプレートタグのマニュアルと、テーマ適用ルールを示したグラフ。何かわからないことがあったらまずはマニュアル確認。

ページごとにユニークなタイトル

ページごとにユニークなタイトルを付ける。検索エンジン対策では基本中の基本。


<?php if(is_single()|| is_page()|| is_category()): ?><title><?php echo trim(wp_title('',FALSE)); if(wp_title('',FALSE)) ?></title>
<?php elseif(is_home()): ?><title><?php bloginfo('name'); ?></title>
<?php else: ?><title><?php echo trim(wp_title(' | ',TRUE,'right')); if(wp_title('',FALSE)) ?><?php bloginfo('name'); ?></title>
<?php endif; ?>

わたしの場合は投稿ページ・カテゴリページのタイトルからBLOG名を外している。記事のタイトルを前に持ってくると、なぜか先頭に半角スペースが入るので、トリミングしています。

「記事名 | BLOG名」でよければ、ずっとシンプルに次のように記述すればいいのでは。


<title><?php echo trim(wp_title('', false)); if (wp_title('', false)) ?></title>

なお、タイトルはSEO対策プラグインで簡単に操作できる。

ページごとにユニークなdescription

ページごとにユニークな説明文を付ける。検索エンジンでは検索結果の説明・引用文になるので、非常に重要。とりあえずこんな感じで……


<?php if(is_single()|| is_page()): if(have_posts()): while(have_posts()): the_post(); ?><meta name="description" content="<?php $excerpt = strip_tags(get_the_excerpt()); echo $excerpt; ?>" />
<?php endwhile; endif; elseif(is_home()) : ?><meta name="description" content="<?php bloginfo('description'); ?>" />
<?php elseif(is_category()): ?><meta name="description" content="<? foreach((get_the_category()) as $cat) {echo $cat->category_description . '';} ?>" />
<?php elseif(is_tag()): ?><meta name="description" content="<?php $posttags = get_the_tags(); if ($posttags) {foreach($posttags as $tag) {echo $tag->description . '';}}?>" />
<?php endif; ?>

月別アーカイブは無視。検索エンジンにインデックスさせないんでいらないかと。カテゴリやタグをインデックスさせないのならis_category()is_tag()の部分は削除してもよいでしょう。

ちなみに、descriptionを記述しなかった場合、本文の先頭部分から自動的にdescriptionを抽出するようにしたいのならば、ここらへんを参照のこと。

なお、descriptionはSEO対策プラグインで簡単に操作できます。

アーカイブを検索エンジンにインデックスさせない

アーカイブページとカテゴリページを検索エンジンにインデックスさせないために「noindex」を追加。検索エンジンが重複コンテンツを嫌うとかなんとかいう理由で、SEO対策済みのテンプレートなどを見ているとこのように処理されています。


<?php if(is_date()|| is_category()): ?><meta name="robots" content="noindex,follow" />
<?php endif; ?>

カテゴリをインデックスさせるなら|| is_category()を削除。

なお、noindexの追加についてもSEO対策プラグインで簡単に操作できます。

wp_headから不要なコードを削除

head部分には自動的にいろいろなコードが挿入されますが、重要性の低いものも多々あります。あってもなくてもどうでもよいものは削除してしまった方がすっきりするのではないでしょうか。

そんな訳で、わたしの場合はfunctions.phpに次のコードを追加しています。


remove_action('wp_head', 'rsd_link');
remove_action('wp_head', 'wlwmanifest_link');
remove_action('wp_head', 'wp_generator');
remove_action('wp_head', 'start_post_rel_link');
remove_action('wp_head', 'index_rel_link');
remove_action('wp_head', 'adjacent_posts_rel_link');
remove_action('wp_head', 'wp_shortlink_wp_head');

なお、この部分についてもSEO対策プラグインで簡単に操作できます。

テーマのモジュール化

WPはホーム(home.php)・投稿ページ(single.php)・カテゴリ(category.php)・アーカイブ(archive.php)など、それぞれに異なるテンプレートを当てることができますが、それらの中で共通する部分をモジュール化してインクルードすることもできます。

header.phpやfooter.php、sidebar.phpも同じ発想だが、これをさらに細かくパーツ化したものです。

MTでそのように管理していたので、WPでも同じようにテンプレートをパーツに分割しました。こんな感じでインクルードすることができます。


<?php include (TEMPLATEPATH . '/aaa.php'); ?>

ディレクトリで階層化できるので、ファイルが多くなる場合はフォルダを作って管理した方がすっきりします。

パンくずリスト

プラグインを使わなくても実装可能。リスト形式でマークアップすればこんな感じになります。


<ul>
<li><a href="<?php bloginfo('url'); ?>">ホーム</a> &raquo;</li>
<?php if(is_category()): ?>
<li> &raquo;<?php
foreach((get_the_category()) as $cat) {
echo get_category_parents($cat, TRUE, ' &raquo; ');
} ?></li>
<?php elseif(is_single()): ?>
<li> &raquo;<?php
foreach((get_the_category()) as $cat) {
echo get_category_parents($cat, TRUE, ' &raquo; ');
} ?></li>
<li><?php the_title() ?></li>
<?php else: ?>
<li> &raquo;<?php echo trim(wp_title('',FALSE)); if(wp_title('',FALSE)) ?></li>
<?php endif; ?>
</ul>

ただ、このコードではサブカテゴリが存在する場合少し不自然になります。良い対策方法が見つからなかったので、ひとまずプラグインで実装しました。プラグインについてはこちらを参照。

パンくずリストは奥が深そうなので、参考になりそうなリンクを集めてみました。

「続きを読む」に記事タイトル名を追加

「続きを読む」に記事タイトル名を追加する場合は、functions.phpに次のようなコードを追加します。


function moretag_custom($content) {
    if (is_page() || is_single()) {
        $content = preg_replace('/(?:<p>)*<span id="more-([0-9]+?)"><\/span>(.*?)(?:<\/p>)*/i', "\r
</div>\r
<div id=\"more\" class=\"entry\">\r
$2", $content);
    }else{
        $content = preg_replace('/<p>\s*<a href="(.+?)#more" class="more-link">(.+?)<\/a><\/p>/', '<p class="more"><a href="$1#more" class="more-link">$2</a></p>', $content);
    }
    return $content;
}
 
function custom_more_link( $more_link, $more_link_text ) {
    $more_link = preg_replace('/#more-[\d]+/i', '#more', $more_link );
    return str_replace($more_link_text, "続きを読む &raquo; ".the_title('', '', false)." &raquo;", $more_link);
}
add_action('the_content', moretag_custom, 100);
add_filter( 'the_content_more_link', 'custom_more_link', 10, 2 );

このコードはWebTecNoteさんよりいただきました。表示部分だけ少し変更してますが。

記事リストに抜粋表示

インデックス(ホーム・カテゴリ・アーカイブ)ページで表示する記事の一覧は、標準では「more」の前に記述した内容が表示されますが、それを「description」(記事抜粋)に置き換えます。

実装は極めて簡単で、


<?php the_content(); ?>


<?php the_excerpt(); ?>

に置き換えるだけ。ただし、「the_excerpt();」はBody内ではデフォルトでPタグ付きで出力されます。Pタグを外したい場合は


<?php $excerpt = strip_tags(get_the_excerpt()); echo $excerpt; ?>

のように記述すれば、タグを外して出力させることができます。

記事リストの表示順

インデックス(ホーム・カテゴリ・アーカイブ)ページで表示する記事の一覧は、標準では新しいもの順に表示されますが、場合によっては、古い順に並べたいこともあるかと。

その場合、次のコードを「have_posts」の前に追加します。


<?php $paged = get_query_var('paged'); query_posts('posts_per_page=10&order=asc&paged='.$paged); ?>

で、こんな感じになるかと……


<?php $paged = get_query_var('paged'); query_posts('posts_per_page=10&order=asc&paged='.$paged); ?>
<?php if (have_posts()) : ?>
<?php while (have_posts()) : the_post(); ?>

このコードはWordPress & Business メモさんよりいただきました。

「query posts」タグは、かなりいろんなことができるようです。詳しくはCodexを参照のこと。

のように記述すれば、タグを外して出力させることができます。

特定カテゴリ・特定タグの記事リスト表示

特定のカテゴリや特定のタグの記事リストを作ります。「query_posts」で簡単に実装可。

カテゴリの場合


<?php query_posts($query_string . '&category_name="カテゴリスラッグ"&showposts=10'); ?>
<?php if(have_posts()):while(have_posts()):the_post(); ?>
<a href="<?php the_permalink() ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?>
<?php endwhile; endif; ?>

上記の例はカテゴリースラッグ名で指定した場合。「showposts」は表示数。※引数はCodexを参照。

カテゴリーの引数は下記の通り。

  • cat(整数):カテゴリー ID
  • category_name (文字列):カテゴリースラッグを指定(カテゴリー名ではない)
  • category_and (配列):カテゴリー ID の配列。指定した複数のカテゴリーすべてに含まれる投稿のみを表示
  • category_in (配列):カテゴリー ID の配列。指定した複数のカテゴリーいずれかに含まれる投稿のみを表示
  • category_not_in (配列):カテゴリー ID の配列。指定した複数のカテゴリーのいずれにもに含まれない投稿のみを表示

タグの場合


<?php query_posts($query_string . '&tag="タグ名"&showposts=5'); ?>
<?php if(have_posts()):while(have_posts()):the_post(); ?>
<a href="<?php the_permalink() ?>" title="<?php the_title_attribute(); ?>"><?php the_title(); ?></a></dt>
<?php endwhile; endif; ?>

上記の例はタグ名で指定した場合。「showposts」は表示数。

タグの引数は下記の通り。

  • tag (文字列):タグスラッグを指定
  • tag_id (整数):タグ ID を指定。コンマ区切りにした複数 ID の文字列も指定可能
  • tag_and (配列):タグ ID の配列。指定した複数のタグのすべてを含む投稿のみを表示
  • tag_in (配列):タグ ID の配列。指定した複数のタグのいずれかを含む投稿のみを表示
  • tag_not_in (配列):タグ ID の配列。指定した複数のタグのいずれも含まない投稿のみを表示
  • tag_slug_and (配列):タグスラッグの配列。指定した複数のタグすべてを含む投稿のみを表示
  • tag_slug_in (配列):タグスラッグの配列。指定した複数のタグのいずれかを含む投稿のみを表示。

関連記事の表示

現在の記事と同じタグの記事を表示します。


<?php $tags = wp_get_post_tags($post->ID);
if ($tags) : ?>
<ul id="related-post">
<?php
  $first_tag = $tags[0]->term_id;
  $args=array(
    'tag__in' => array($first_tag),
    'post__not_in' => array($post->ID),
    'posts_per_page '=>5, //5件
    'caller_get_posts'=>1
  );
  $my_query = new WP_Query($args); 

  if( $my_query->have_posts() ) {
    while ($my_query->have_posts()) : $my_query->the_post(); ?>

    <li><a href="<?php the_permalink() ?>" rel="bookmark" title="Permanent Link to <?php the_title_attribute(); ?>">
    <?php the_title(); ?></a></li>
    <?php endwhile; wp_reset_query(); ?>
</ul>
<?php endif ?>

このコードはWebデザインレシピさんよりいただきました。

最終更新日を表示

最終更新日はテンプレートタグ「the_modified_time」や「the_modified_date」で表示できますが、公開時間と更新時間が同じ場合でも表示され、また予約投稿を行なうと公開時間より早い更新時間が表示されてしまいます。更新時間が公開時間より後の場合のみ表示されるようにするには、functions.phpに次のコードを追加します。


function get_mtime($format) {
    $mtime = get_the_modified_time('Ymd');
    $ptime = get_the_time('Ymd');
    if ($ptime > $mtime) {
        return get_the_time($format);
    } elseif ($ptime === $mtime) {
        return null;
    } else {
        return get_the_modified_time($format);
    }
}

テーマ側の表示したい部分に下のコードを追加。「最終更新日:」の部分は自由に書き換え可。HTMLタグもOK。


<?php if ($mtime = get_mtime('Y/m/d')) echo '最終更新日: ', $mtime; ?>

このコードはfiregobyさんよりいただきました。

ページナビゲーション

インデックス(ホーム・カテゴリ・アーカイブ)ページで表示する記事の一覧をページ分けします。プラグインで実装する人が多いみたいですが、プラグインなしでも可能です。わたしは次のサイトで公開されているものをそのまま使っております。

Yuriko.Net » WP-PageNavi を使わずにナビゲーション表示

プラグインで実装したい場合はこちらを参照。

カテゴリごとに個別記事のテーマ・テンプレートを変更

「in_category()」で条件分岐することで、カテゴリごとにデザインを変更できます。「()」の中にはカテゴリのスラッグを入れます。例はスラッグが「car」の場合。


<?php if(in_category('car')): ?>

テーマをモジュール化するとすっきりするので組み合わせて使うのがおすすめ。

404 Not Found

404エラーページ用のテンプレートの最初に次のコードをつけるといいみたいです。


<?php header("HTTP/1.1 404 Not Found"); ?>

詳しくはリンク先をご確認のこと。