WordPressのテーマを自作する方法【オリジナルテーマ開発】

今回は、オリジナルのWordPressテーマを自作する方法を紹介します。

かなり長い記事ですが、数日かけてでも読んで実際にコードを書いて欲しいと思います。

WordPressサイトを自分で制作したいという方はぜひご覧ください。

WordPress開発に最低限必要な知識

WordPress開発には、以下のスキル・知識が必要になります。

  • HTML/CSS
  • PHPの基礎
  • JavaScriptの基礎(使わない場合もあります)
  • WordPressの使用経験

上記を学んだ経験がない場合は、まずはそちらから学習してください。

開発環境

WordPressの開発環境には、「Local by Flywheel」を使うのがおすすめです。

XAMPPやMAMPのようなPHP環境を用意しなくて、簡単にWordPress開発環境を構築できます。

Local by Flywheelの導入方法は以下の記事をご覧ください。

Mac向けの記事ですが、Windowsでも手順はほぼ同じです。

ブラウザはGoogle Chromeで解説します。

エディターに指定はありませんが、無料で使えるVSCodeが高機能で使いやすくおすすめです。

Localでローカル環境にWordPressサイトを作成

上記記事でWordPressサイトをローカル環境に作成する方法は解説しています。

今回は、「my theme」と名前をつけて作成していきます。

設定は「Preferred」のまま進めます。

あとはユーザー名とパスワードを設定したら完了です。

作成できたら、WordPressにログインします。

「WP Admin」ボタンから管理画面に入れます。

先ほど設定したユーザー名とパスワードを入れてログインしてください。

初期設定では表示が英語になっているので、これを変更します。

管理画面の「Settings」にある、「Site Language」を日本語に、「Timezone」を「UTC+9」に変更してください。

これでローカル環境の用意は完了です。

テーマファイルを作成

上記で作成したサイトのフォルダは、「Go to site folder」から開けます。

テーマのフォルダは、「app」→「public」→「wp-content」→「themes」に作成します。

今回は、ここに「my-theme」と名付けたフォルダを作成します。

作成した「my-theme」フォルダに、テーマのファイルを作成していきます。

テーマの最小構成は、

  • index.php
  • style.css

この2つのファイルです。まずはこれを「my-theme」フォルダに作成します。

style.cssにテーマの情報を記述します。

style.css
/*
Theme Name: My Theme
Author: Your Name
Description: My First WordPress Theme
Version: 1.0
Text Domain: mytheme
*/

テーマの情報は、style.cssの一番上に上記のようなコメントアウトで記述します。

  • Theme Name → テーマの名前
  • Author → テーマの制作者
  • Description → テーマの説明
  • Version → テーマのバージョン
  • Text Domain → テキストドメイン

テキストドメインは、テーマファイル内のテキストの翻訳に対応するために記述します。

コメントアウトの情報は他にもありますが、長くなるので割愛します。詳しくは以下のリンクからご覧ください(英語)。

Main Stylesheet (style.css) | Theme Developer Handbook | WordPress Developer Resources

index.phpは一旦「Hello WordPress!」と書いておきます。

index.php
<p>Hello WordPress!</p>

ここまで書けたら、WordPress管理画面の「外観」にテーマが表示されるかと思います。

My Themeを有効化して、ブラウザで表示を確認してみましょう。

「Hello WordPress!」と表示されればテーマの反映は完了です。

デバッグ

PHPにエラーがないか確認するために、デバッグモードをオンにしましょう。

Localを使っている場合は、「app」→「public」フォルダにwp-config.phpファイルがあるので、こちらを開きます。

wp-config.php
if ( ! defined( 'WP_DEBUG' ) ) {
	define( 'WP_DEBUG', true );
}

こちらは開発環境のみでtrueにしてください。本番サイトではtrueにしないでください。

もしくは、プラグインでエラーを確認する方法もあります。

「プラグイン」→「新規プラグインを追加」で、「query monitor」と検索してください。

こちらを有効化しておくと、エラーの確認や処理にかかった時間の把握ができるので便利です。

個人的にはQuery Monitorでエラーの確認をしています。

実際にコードを書いていこう

では、index.phpに記述していきます。

※実際の制作ではindex.phpはあまり使いません。その点は後ほど説明します。

Hello WordPress!のHTMLは削除してください。

基本的なコードを記述する

まずはベースとなるHTMLを記述します。

index.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    
</body>
</html>

lang=”ja”の部分は、WordPressの言語設定に合わせるようにするため、以下のように書き換えます。

index.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    
</body>
</html>

language_attributes関数は、設定している言語のlang属性を自動で出力してくれます。設定を日本語にしている場合は、自動で「lang=”ja”」が出力されます。

このように、WordPressには便利な関数が豊富に用意されているので、それを記述するだけで複雑な処理を簡単に実装することができます。

次にwp_head関数とwp_footer関数を追加します。

index.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body>
    
<?php wp_footer(); ?>
</body>
</html>

wp_head関数を入れると、タイトルや各種metaタグ、WordPress本体(コア)のCSSなどが自動で出力されます。これはテーマには必須の関数です。

wp_footer関数を記述すると、コアのJavaScriptが出力されたり、ログインユーザー用のツールバーが表示されたりします。

次に、bodyにbody_class関数を記述します。

index.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    
<?php wp_footer(); ?>
</body>
</html>

body_class関数を入れるとページによって異なるクラス名が付与されるので便利です。

次に、wp_body_open関数を記述します。

index.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    
    <?php wp_footer(); ?>
</body>
</html>

これはbody開始タグ直後にコードを挿入したい時に使うので、入れておいた方がいいでしょう。

あとは、HTMLを以下のように記述していきます。

index.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    <div class="container">
        <header class="header">
            ここがヘッダーです
        </header>
        <div class="contents">
            ここがコンテンツです。
        </div>
        <footer class="footer">
            ここがフッターです。
        </footer>
    </div>
    <?php wp_footer(); ?>
</body>
</html>

functions.phpの作成

次に、functions.phpファイルを作成します。

functions.phpにはindex.phpのようにサイトに表示されるHTMLを書くのではなく、処理を追加する役割があります。

では、functions.phpに以下のコードを記述してください。

functions.php
<?php

function my_theme_setup() {
	add_theme_support( 'title-tag' );
}
add_action( 'after_setup_theme', 'my_theme_setup' );

これは、headにtitleタグを出力する処理です。

まず、my_theme_setup関数を定義します。

関数を独自に定義する際、WordPress本体やプラグインで定義された関数と被らないように、「my_theme_」のような接頭辞(プレフィックス)をつけるようにしましょう。

add_theme_support関数は、テーマがサポートする機能を追加できます。引数にはサポートする機能を記述します。

引数の値は、以下のページを参考にしてください。

add_theme_support() | Function | WordPress Developer Resources

add_actionは、第一引数で指定したタイミングで処理を追加できます。

このように、特定のタイミングで処理を追加できる機能を、WordPressではフック(hook)と呼びます。

add_action( 'after_setup_theme', 'my_theme_setup' );

このコードは、「テーマが読み込まれた時に、my_theme_setup関数を呼び出す」という内容の処理になります。

functions.phpを保存したらサイトでGoogle Chromeの右クリックで表示される「ページのソースを表示」を見てみましょう。

このように、wp_head関数がある位置にtitleタグが出力されています。

titleタグの中身はページに応じて自動で変わるようになります。

他の機能もいくつか追加しておきます。

functions.php
function my_theme_setup() {
	// タイトルを自動出力
	add_theme_support( 'title-tag' );

	// アイキャッチ機能を使用
	add_theme_support( 'post-thumbnails' );

	// 埋め込みのレスポンシブ自動対応
	add_theme_support( 'responsive-embeds' );

	// feedの自動生成
	add_theme_support( 'automatic-feed-links' );

	// 抜粋のサポート
	add_theme_support( 'excerpt' );

	// HTML5に対応させる
	add_theme_support(
		'html5',
		array(
			'comment-form',
			'comment-list',
			'gallery',
			'caption',
			'style',
			'script',
			'search-form',
			'navigation-widgets',
		)
	);
}
add_action('after_setup_theme', 'my_theme_setup' );

他にも追加できる機能はありますが、基本的なものだけ記述しています。

ファイルを分割する

サイト共通で使う部分は、ファイルを分割して各ページで読み込むようにします。

ます、ヘッダー用のheader.php、フッター用のfooter.phpを作成します。

先ほどindex.phpに記述したコードを、header.phpとfooter.phpに移動します。

header.phpには以下のコードを移動します。

header.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    <div class="container">
        <header class="header">
            ここがヘッダーです
        </header>

footer.phpには以下のコードを移動します。

footer.php
		<footer class="footer">
            ここがフッターです。
        </footer>
    </div>
    <?php wp_footer(); ?>
</body>
</html>

作成したheader.phpとfooter.phpを読み込むには、以下のように記述します。

index.php
<?php get_header(); ?>
<div class="contents">
    ここがコンテンツです。
</div>
<?php get_footer(); ?>

get_header関数はheader.phpと名付けたファイルを自動で出力してくれる関数です。

同様にget_footerはfooter.phpと名付けたファイルを読み込みます。

ブラウでみてみると、ちゃんとヘッダーとフッターが読み込まれているのがわかります。

ヘッダーにサイト名を表示

ヘッダーにサイト名を表示させます。

header.phpに以下のように記述します。

header.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    <div class="container">
        <header class="header">
            <div class="header__inner">
                <h1 class="site-name">
                    <a href="<?php echo home_url(); ?>">
                        <?php bloginfo( 'name' ); ?>
                    </a>
                </h1>
            </div>
        </header>

home_url関数は、サイトのURLを取得する関数です。

bloginfo関数はブログの情報を取得する関数です。引数に'name'を指定すると、サイト名を取得できます。

その他取得できる情報は、以下のリンクで確認してください。

bloginfo() | Function | WordPress Developer Resources

ブラウザを確認すると、以下のようにサイト名がヘッダーに表示されているはずです。

装飾が一切されていない状態なので、以下の手順でスタイルを適用させていきます。

CSSを読み込む

WordPressでCSSを読み込む時は、headに直接記述するのではなく、専用の関数を使って読み込みます。

functions.phpに以下のコードを追加してください。

functions.php
function my_theme_enqueue_scripts() {
	$template_url = get_template_directory_uri();
	wp_enqueue_style( 'theme-style', $template_url . '/style.css', array(), '1.0.0' );
}
add_action('wp_enqueue_scripts', 'my_theme_enqueue_scripts');

get_template_directory_uri関数は、テーマフォルダのURLを取得する関数です。

wp_enqueue_style関数は、CSSを読み込む関数です。

wp_enqueue_style( $handle, $src = '', $deps = array(), $ver = false, $media = 'all' )
  • $handle・・・スタイルの名前。他と被らないような名前をつけてください。
  • $src・・・CSSファイルの場所。
  • $deps・・・特定のCSSの後に読み込みたい場合に使用します。他のCSSの$handleを記述することで、そのCSSの後に読み込まれます。
  • $ver・・・バージョン情報です。キャッシュをリフレッシュできるので、テーマのバージョンを記述すると良いでしょう。
  • $media・・・’all’、’screen’、’print’が選択できます。デフォルトのままで使うことがほとんどなので、省略してOK。

バージョンのところは、自動化した方が楽なので、以下のように書き換えます。

functions.php
function my_theme_enqueue_scripts() {
	$template_url = get_template_directory_uri();
	$theme = wp_get_theme( get_template() );
	$version = $theme->Version;
	wp_enqueue_style( 'theme-style', $template_url . '/style.css', array(), $version );
}
add_action('wp_enqueue_scripts', 'my_theme_enqueue_scripts');

wp_get_theme関数でテーマの情報を取得して、そこからテーマのバージョンを取得しています。

ブラウザのソースを確認すると、以下のようにlinkタグが追加されているはずです。

試しにCSSを記述してみましょう。

style.css
/*
Theme Name: My Theme
Author: Your Name
Description: My First WordPress Theme
Version: 1.0
Text Domain: mytheme
*/

body {
    margin: 0;
    background-color: #f7f7f7;
    color: #333;
}
*,
*:before,
*:after {
    box-sizing: border-box;
}

.header {
    background-color: #fff;
}
.header__inner {
    width: 90%;
    margin: auto;
    padding: 10px 0;
}
.site-name {
    margin: 0;
    font-size: 20px;
}
.site-name a {
    color: currentColor;
    text-decoration: none;
}
.contents {
    padding: 40px 0;
}

ブラウザを確認すると、CSSが適用されているはずです。

グローバルナビを作成する

サイト共通部分のヘッダーとその中に入るグローバルナビを作成していきます。

ヘッダーはheader.phpに記述します。

その前に、表示のテスト用にタイトルだけ書いた空の固定ページを2ページほど作成しておいてください。

このページを、グローバルナビで表示するようにします。

先ほど記述したmy_theme_setupregister_nav_menus関数を追加します。

functions.php
function my_theme_setup() {
	// ~ 省略 ~

    register_nav_menus( array(
        'global-nav' => 'グローバルナビ',
    ) );
}
add_action('after_setup_theme', 'my_theme_setup' );

register_nav_menus関数の引数には、配列でメニューの設定を記述します。

register_nav_menus( array(
    '識別子' => '設定画面に表示されるメニューの名前',
) );

翻訳できるようにするには、以下のように記述します。

functions.php
function my_theme_setup() {
	// ~ 省略 ~

    register_nav_menus( array(
        'global-nav' => __( 'Global Navigation', 'mytheme' ),
    ) );
}
add_action('after_setup_theme', 'my_theme_setup' );

テキストは__( '英文', 'Text Domain');の形にしておくと、翻訳に対応できます。

多言語サイトを作る際や公式ディレクトリに登録する場合は必要にですが、一般的な制作では翻訳に対応しなくてもいいでしょう。

話がそれましたが、これでWordPress管理画面の「外観」に「メニュー」という項目が追加されます。

今回は、グローバルナビと名付けたメニューを作成します。メニュー設定の「グローバルナビ」にチェックを入れて保存してください。

このメニューを、header.phpで表示させます。

header.php
<!DOCTYPE html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
    <?php wp_body_open(); ?>
    <div class="container">
        <header class="header">
            <div class="header__inner">
                <h1 class="site-name">
                    <a href="<?php echo home_url(); ?>">
                        <?php bloginfo( 'name' ); ?>
                    </a>
                </h1>
                <?php
                    if ( has_nav_menu( 'global-nav' ) ) {
                        wp_nav_menu(array(
                            'theme_location' => 'global-nav',
                            'menu_class' => 'global-nav__list',
                            'container' => 'nav',
                            'container_class' => 'global-nav',
                            'depth' => 1,
                        ));
                    }
                ?>
            </div>
        </header>

has_nav_menu関数で'global-nav'の名前で登録したメニュー設定に、メニューが登録されているかチェックします。

wp_nav_menu関数でメニューを表示します。引数には表示方法を指定した配列が入ります。

  • theme_location・・・表示したいメニューの識別子。
  • menu_class・・・メニューのクラス名。
  • container・・・メニューを囲むHTMLタグ。
  • container_class・・・メニューを囲むHTMLのクラス名。
  • depth・・・階層の深さ。無限にする場合は、0を指定します。

これでヘッダーにグローバルナビが表示されます。

あとはCSSで調整して、このような形にしました。

投稿一覧を表示する

では、トップページとなる投稿一覧を作成します。

HTMLでサイトを作るときは、一般的にindex.htmlでトップページを作成しますが、WordPressではindex.phpではなくhome.phpを使用します(トップページが投稿一覧の場合)。

トップページ用のファイルにはfront-page.phpが使われる場合もありますが、それぞれの違いは以下になります。

  • home.php → 投稿一覧ページ。
  • front-page.php → 投稿一覧ではなく、固定ページでトップページを作る場合に使用。
  • index.php → テンプレートファイルが見つからなかった場合に最終的に使用されるファイル。

ブログのようなサイトではトップページにhome.phpが使われることが多く、コーポレートサイトのようにトップページが投稿一覧ではない場合はfront-page.phpが使われることが多いです。

テスト用の投稿を作成

投稿一覧に表示される記事がまだないので、テスト用の投稿を作成します。

自分で用意してもいいですが、公開されているデータをインポートするという方法もあります。

今回はテストデータをインポートして進めます。

https://github.com/jawordpressorg/theme-test-data-ja

上記URLにアクセスして、緑色ボタンの「Code」の「Download ZIP」でテストデータをダウンロードできます。

テストデータをダウンロードしたら、WordPress管理画面の「ツール」→「インポート」に進みます。

インポートツールの「WordPress」の「今すぐインストール」をクリックします。

インストールできたら「インポートの実行」をクリックします。

先ほどダウンロードしたZIPファイルを展開すると、「wordpress-theme-test-data-ja.xml」というファイル名がありますので、これをインポートします。

ファイルを選択して「ファイルをアップロードしてインポート」をクリックします。

「添付ファイルをダウンロードしてインポートする」にチェックを入れて、実行してください。

インポートが完了したら、テスト用の投稿が豊富に作成された状態になります。

その他、テスト用の固定ページやメニューも追加されます。

ループ

まず、home.phpを作成します。

作成したら、以下のように記述します。

home.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <p class="entry-item__ttl">
                                <?php the_title(); ?>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
        </main>
    </div>
</div>
<?php get_footer(); ?>

get_headerget_footerは前述した通りです。

have_posts関数は、投稿があるかをチェックする関数です。投稿があればtrueを返します。

while ( have_posts() ) :

このコードは、have_post関数がfalseを返すまで繰り返すループ処理になります。

the_post関数は、次の投稿に進める処理をします。

the_post()で最新の投稿から順番に進めていき、次の投稿がなくなるとhave_posts()がfalseを返し、whileループから抜けるという処理内容になります。

このループは全投稿分ループするのではなく、「設定」→「表示設定」の「1ページに表示する最大投稿数」分ループします。デフォルトでは10件までです。

the_title関数は、ループ内で現在の投稿のタイトルを表示します。

では表示を確認してみましょう。

投稿一覧が表示されました。

数えてみると11件出力されています。これは先頭固定表示されている投稿がある影響です。

「先頭固定表示」は投稿日時に関わらず一覧の最初に優先的に表示させる設定です。

「先頭固定表示」の投稿はカウントに含まれず、11件表示されてしまうのです。

ややこしいで一旦この投稿は下書きにしておきましょう。

これで10件表示される状態になりました。

現状タイトルのみの表示なので、その他の情報が表示されるように修正します。

home.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <a href="<?php the_permalink(); ?>" class="entry-item__thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'medium', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </a>
                            <p class="entry-item__ttl">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </p>
                            <p class="entry-item__date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
        </main>
    </div>
</div>
<?php get_footer(); ?>

これでアイキャッチ画像、投稿へのリンク、投稿日時が表示されるようになりました。

  • the_permalink関数は投稿のURL
  • has_post_thumbnail関数はアイキャッチ画像が設定されているかの確認
  • the_post_thumbnail関数はアイキャッチ画像(サムネイル)のHTMLを出力する関数。第一引数は画像のサイズ、第二引数には属性を配列の形で指定できます。
  • get_the_date関数は投稿日時を取得できます。'Y-m-d'は表示するフォーマットです。フォーマットを省略した場合、「設定」の「日付形式」のフォーマットで出力されます。

いずれの関数も引数に投稿IDを入れて使いますが、ループ内で使う場合は省略できます。

CSSで調整をして、以下のように表示されるようにしました。

ページ送りの表示

このままで11件目以降の投稿が見れないので、ページ送り(ページネーション・パジネーション・ページャー)を表示させます。

home.phpに以下のように追記します。

home.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <a href="<?php the_permalink(); ?>" class="entry-item__thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'medium', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </a>
                            <p class="entry-item__ttl">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </p>
                            <p class="entry-item__date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
            <div class="pager">
                <?php
                    echo paginate_links(array(
                        'type' => 'list',
                        'prev_text' => '&lt;',
                        'next_text' => '&gt;',
                    ));
                ?>
            </div>
        </main>
    </div>
</div>
<?php get_footer(); ?>

paginate_links関数は、ページ送りのHTMLを取得する関数です。

引数に配列を入れて、さまざまな設定ができます。

paginate_links() | Function | WordPress Developer Resources

追記すると、以下のようにページ送りが表示されます。

CSSで表示を整えます。

こんな感じにしてみました。

サイドバー(ウィジェットエリア)を作成

ブログサイトでは一般的に、右サイドバーにカテゴリー一覧やタグ一覧、月別リスト、検索フォームなどが表示されます。

これらは自分で用意するのではなく、WordPress本体で用意されているウィジェットを利用することがほとんどです。

ここでは、管理画面から追加・編集ができるウィジェットエリアを追加していきます。

サイドバーを作成する前に、ウィジェットの登録から行います。

functions.phpに以下のコードを追加してください。

functions.php
function my_theme_widget_settings() {
    register_sidebar( array(
        'name' => 'サイドバー',
        'id' => 'sidebar',
        'description' => 'サイドバーに表示されます',
        'before_widget' => '<div id="%1$s" class="widget widget--sidebar %2$s">',
        'after_widget'  => '</div>',
        'before_title'  => '<h2 class="widget__ttl">',
        'after_title'   => '</h2>',
    ) );
}
add_action('widgets_init', 'my_theme_widget_settings');

register_sidebar関数は、ウィジェットを登録する関数です。

functions.phpにこのコードを追加すると、管理画面の「外観」に「ウィジェット」が追加されます。

nameには表示されるウィジェットの名前、idは他のウィジェットと区別するための識別子、descriptionは右サイドバーに表示される説明です。

before_widgetafter_widgetはウィジェットの前後に追加するHTML。before_titleafter_titleはタイトルの前後に追加するHTMLです。

ウィジェット用のブロックは以下のようなものが用意されています(WordPress6.4現在)。

今回は、

  • 「ウィジェットグループ」を選択し、その中に「カテゴリー一覧」ブロック
  • 「ウィジェットグループ」を選択し、その中に「検索」ブロック

を入れて、試してみます。

ウィジェットを追加して保存したら、サイドバーを作成していきます。

sidebar.phpファイルを作成して、以下のコードを記述してください。

sidebar.php
<aside class="sidebar">
    <div class="sidebar__inner">
        <?php if ( is_active_sidebar( 'sidebar' ) ) : ?>
            <?php dynamic_sidebar( 'sidebar' ); ?>
        <?php endif; ?>
    </div>
</aside>

is_active_sidebar関数は、ウィジェットエリアのIDを引数に入れて、そのウィジェットエリアにウィジェットが存在するか確認します。

先ほど検索ボックスやカテゴリーを追加したので、is_active_sidebartrueを返します。

dynamic_sidebar関数は、ウィジェットエリアのIDを引数に指定して、ウィジェットを表示します。

sidebar.phpが作成できたら、home.phpに以下のようにコードを追加します。

home.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <a href="<?php the_permalink(); ?>" class="entry-item__thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'medium', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </a>
                            <p class="entry-item__ttl">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </p>
                            <p class="entry-item__date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
            <div class="pager">
                <?php
                    echo paginate_links(array(
                        'type' => 'list',
                        'prev_text' => '&lt;',
                        'next_text' => '&gt;',
                    ));
                ?>
            </div>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

get_sidebar関数を追加しました。その名の通り、sidebar.phpと名付けたファイルを読み込む関数です。

表示を確認すると、以下のように投稿一覧の下にウィジェットが表示されるはずです。

あとはCSSでサイドバーが右側に来るようにして、若干の修正をして以下のようにしました。

投稿を表示する

投稿一覧が作成できたので、次は投稿ページを作成します。

投稿はsingle.phpで作成します。

大枠はhome.phpからコピーして使い回します。

single.phpに、以下のように記述してください。

single.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <?php if ( have_posts() ) : ?>
                <?php while ( have_posts() ) : the_post(); ?>
                    <article class="article">
                        <header class="entry-header">
                            <h1 class="entry-title"><?php the_title(); ?></h1>
                            <p class="entry-date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                            <div class="entry-category">
                                <?php the_category(); ?>
                            </div>
                            <div class="entry-tag">
                                <?php the_tags( '<ul><li>', '</li><li>', '</li></ul>' ); ?>
                            </div>
                            <div class="entry-thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'large', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </div>
                        </header>
                        <div <?php post_class( 'entry-content' ); ?>>
                            <?php the_content(); ?>
                        </div>
                    </article>
                <?php endwhile; ?>
            <?php endif; ?>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

「あれ?ループさせるの?」と思った方もいるかもしれません。投稿ページでは1回だけループさせます。

理由としては、ループ内でしか使えない関数があるので、それを利用できるようにするためです。

the_category関数は投稿に設定されているカテゴリーを全て表示させます。

the_tags関数は、投稿に設定されているタグを表示させます。第一引数はリストの前に表示させるHTML、第二引数はリストの項目の間に表示させるHTML、第三引数はリストの後に表示させるHTMLを記述します。

post_class関数は、投稿IDや設定によって異なるクラス名をつけてくれる関数です。引数に独自のクラス名を追加することができます。

the_content関数は、投稿本文を出力する関数です。

ブラウザで表示を確認すると、以下のようになりました。

タイトルや投稿日、カテゴリー、タグ、アイキャッチ、本文が表示されました。

CSSを整えて、以下のようにしました。

コメント欄を表示する

投稿ページをコメントに対応させる場合は、comments.phpを作成します。

comments.phpを作成して、以下のように記述してください。

comments.php
<?php if ( comments_open() ) : ?>
    <div id="comments" class="comments">
        <?php if ( have_comments() ) : ?>
            <h2 class="comments__ttl">
                コメント<span class="comments__num">(<?php comments_number( '0', '1', '%' ); ?>件)</span>
            </h2>
            <ul class="comments__list">
                <?php wp_list_comments( 'avatar_size=80' ); ?>
            </ul>
        <?php endif; ?>
        <?php if ( get_comment_pages_count() > 1 ) : ?>
            <div class="pager pager--comments">
                <?php
                    paginate_comments_links( array(
                        'prev_text' => '&laquo;',
                        'next_text' => '&raquo;',
                        'mid_size'  => 0,
                    ) );
                ?>
            </div>
        <?php endif; ?>
        <?php
            $args = array(
                'title_reply' => 'コメントする',
                'label_submit' => 'コメントを送信',
                'title_reply_before' => '<h2 class="comment-ttl">',
                'title_reply_after' => '</h2>',
            );
            comment_form( $args );
        ?>
    </div><!-- #comments -->
<?php endif; ?>

comments_open関数は、コメントが許可されているかをチェックします。

comments_number関数は、コメントの件数を取得でき、第一引数には0件だった時のテキスト、第二引数は1件だった時のテキスト、第三引数には2件以上の時のテキスト(%には件数の数字が入ります)を指定します。

wp_list_comments関数でコメントの一覧を出力します。avatar_size=80でアバター画像のサイズが80pxで表示されます。

get_comment_pages_countでコメントのページ数を取得し、複数ページになる場合はページ送りを表示しています。

comment_form関数は、コメントの入力フォームを出力します。

コメントの返信を押した時に、コメント入力フォームを返信する投稿に自動で移動させてくれる機能を設定することもできます。

functions.phpのCSSの読み込みの下にコードを追加します。

functions.php
function my_theme_enqueue_scripts() {

    $template_url = get_template_directory_uri();
    $theme = wp_get_theme( get_template() );
    $version = $theme->Version;
    wp_enqueue_style( 'theme-style', $template_url . '/style.css', array(), $version );

    if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
        wp_enqueue_script( 'comment-reply' );
    }
}
add_action('wp_enqueue_scripts', 'my_theme_enqueue_scripts');

これでコメントに返信するのが楽になります。

single.phpにコードを1行だけ追加して、コメント欄を投稿に表示させます。

single.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <?php if ( have_posts() ) : ?>
                <?php while ( have_posts() ) : the_post(); ?>
                    <article class="article">
                        <header class="entry-header">
                            <h1 class="entry-title"><?php the_title(); ?></h1>
                            <p class="entry-date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                            <div class="entry-category">
                                <?php the_category(); ?>
                            </div>
                            <div class="entry-tag">
                                <?php the_tags('<ul><li>', '</li><li>', '</li></ul>'); ?>
                            </div>
                            <div class="entry-thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'large', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </div>
                        </header>
                        <div <?php post_class( 'entry-content' ); ?>>
                            <?php the_content(); ?>
                        </div>
                        <?php comments_template(); ?>
                    </article>
                <?php endwhile; ?>
            <?php endif; ?>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

comments_template関数でcomments.phpを読み込むことができます。

コードを追加したら、ブラウザで表示を確認してください。コメントが表示されない場合、投稿の「ディスカッション」にある「コメントを許可」にチェックを入れてください。

投稿を確認すると、以下のようにコメント一覧が表示されるはずです。

コメントフォームはページ一覧の下に表示されます。ログインユーザーだと見え方が変わるので、プライベートウィンドウで確認してください。

すでにあるコメントの「返信」をクリックすると、フォームが自動で移動するのを確認してみてください。

テスト投稿の中にコメント欄確認用の投稿がいくつかあるので、それを確認しながらCSSを調整してください。

固定ページを表示させる

固定ページはpage.phpで作成します。

作り方はsingle.phpとほぼ同じです。

page.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <?php if ( have_posts() ) : ?>
                <?php while ( have_posts() ) : the_post(); ?>
                    <div class="page-content">
                        <header class="entry-header">
                            <h1 class="entry-title"><?php the_title(); ?></h1>
                            <div class="entry-thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'large', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </div>
                        </header>
                        <div <?php post_class( 'entry-content' ); ?>>
                            <?php the_content(); ?>
                        </div>
                    </div>
                <?php endwhile; ?>
            <?php endif; ?>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

固定ページにカテゴリーやタグはないので表示しません。

基本的に固定ページに投稿した日時も不要なので、こちらも表示させていません。

固定ページにはコメント欄を設けていないサイトがほとんどなので、今回は除外しました。

カテゴリー・タグ・月別ページを作成する

カテゴリーページ、タグページ、月別ページなどのアーカイブページは、それぞれのファイルを作成するか、archive.phpでまとめて作ります。

  • カテゴリーページはcategory.phpがなければarchive.phpを表示
  • タグページはtag.phpがなければarchive.phpを表示
  • 月別ページはdate.phpがなければarchive.phpを表示

アーカイブページのテンプレートファイルは上記のように表示されます。

今回はarchive.phpでまとめて作成します。

archive.phpはhome.phpとほぼ同じで、ページのタイトルだけ出力されるようにします。

archive.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <h1 class="archive-title">
                <?php the_archive_title(); ?>
            </h1>
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <a href="<?php the_permalink(); ?>" class="entry-item__thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'medium', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </a>
                            <p class="entry-item__ttl">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </p>
                            <p class="entry-item__date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
            <div class="pager">
                <?php
                    echo paginate_links(array(
                        'type' => 'list',
                        'prev_text' => '&lt;',
                        'next_text' => '&gt;',
                    ));
                ?>
            </div>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

the_archive_title関数で、アーカイブページのタイトルを自動で表示できます。

簡単ですね。

検索結果ページの作成

先ほどウィジェットに検索フォームを追加しましたが、検索結果ページをまだ作成していないので検索ができません。

検索結果ページはsearch.phpで作成できます。

archive.phpの中身をコピーして、少し編集するだけで作成できます。

search.phpは以下のように記述してください。

search.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <h1 class="archive-title">
                <?php echo get_search_query(); ?>の検索結果
            </h1>
            <div class="entries">
                <?php if ( have_posts() ) : ?>
                    <?php while ( have_posts() ) : the_post(); ?>
                        <div class="entry-item">
                            <a href="<?php the_permalink(); ?>" class="entry-item__thumb">
                                <?php if ( has_post_thumbnail() ) : ?>
                                    <?php the_post_thumbnail( 'medium', array( 'alt' => get_the_title() ) ); ?>
                                <?php endif; ?>
                            </a>
                            <p class="entry-item__ttl">
                                <a href="<?php the_permalink(); ?>">
                                    <?php the_title(); ?>
                                </a>
                            </p>
                            <p class="entry-item__date">
                                <date datetime="<?php echo get_the_date('Y-m-d'); ?>">
                                    <?php echo get_the_date(); ?>
                                </date>
                            </p>
                        </div>
                    <?php endwhile; ?>
                <?php endif; ?>
            </div>
            <div class="pager">
                <?php
                    echo paginate_links(array(
                        'type' => 'list',
                        'prev_text' => '&lt;',
                        'next_text' => '&gt;',
                    ));
                ?>
            </div>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

archive.phpと異なるのはタイトル(h1)の部分だけです。

get_search_query関数で、検索されたワードを取得できます。

サイドバーの検索フォームで検索してみると、以下のような表示になります。

簡単ですね。

404ページの作成

404用のテンプレートを作成しておかないと、ページが見つからなかった際にindex.phpが表示されてしまいます。

404ページは404.phpで作成します。

404.phpファイルを作成して、以下のコードを記述してください。

404.php
<?php get_header(); ?>
<div class="contents">
    <div class="wrapper">
        <main class="main">
            <div class="page-content">
                <header class="entry-header">
                    <h1 class="entry-title">ページが見つかりませんでした。</h1>
                </header>
                <div class="entry-content">
                    <p>
                        お探しのページは削除されたか、URLが変更になったため見つかりませんでした。
                    </p>
                </div>
            </div>
        </main>
        <?php get_sidebar(); ?>
    </div>
</div>
<?php get_footer(); ?>

404ページではループは回しません。というか回りません。

ここではシンプルなテキストだけでページが存在しないことを伝えています。

スクリーンショットを作成する

テーマ一覧を見てみると、他のテーマには画像が表示されています。

テーマの画像を表示するには、screenshot.pngまたはscreenshot.jpgを作成します。

スクリーンショットは1200x900pxで用意します。

これでテーマ一覧に画像が表示されるようになりました。

これで大まかなテーマの作り方の解説は終了です。

他にもさまざまな機能を追加することができますが、長くなるので別の記事で改めて書いていきたいと思います。

まとめ

今回は、WordPressのテーマを開発する方法を紹介しました。

かなり長くなってしまいましたが、時間をかけて実際に手を動かしてコードを書いてみてください。


その他の記事