WordPressはコーディングの知識がなくても、テーマやプラグインを使って簡単にウェブサイトを作ることができる。しかし、個性を出すために、あるいは自分好みのサイトに仕上げるために、オリジナルテーマの作成に興味のある人は少なくないだろう。
テーマの作成自体も、すでに多くの書籍やウェブサイトに説明がある通り、最低限HTML/CSSが使えればある程度実現できる。ぼくもWordPressを使いたてのころは、何がなんだかわからないまま、手引き通りにテーマを作ったものだ。
ところが残念ながら、このような作成方法をしている限り、WordPressへの理解は一向に深まらない。皮肉なことに、導入や作成のハードルの低さが、逆にユーザの理解を妨げているともいえる。
そこでこの記事では、個人的に「最初に理解しておきたかった」と思えるWordPress関係の知識をひたすら連ねていく。
WordPressはPHPで動いている
WordPressでページを作るとき、すべてのファイルが.phpとなっていることに気づくだろう。HTMLを分解してテーマを作っていた当時は、「こういう決まりなんだ」とあまり深く突き詰めようとしなかった。まずはこの根幹の部分から理解していこう。
PHPとはいったい何なのか
通常、ウェブサイトはHTMLファイルで構成される。ユーザがサイトにアクセスするとサーバはHTMLファイルを返し、それを再度ブラウザが解釈してページを表示する、という仕組みだ。これを「静的なウェブサイト」と呼ぶ。
ところが、ブログサイトのように頻繁にコンテンツを更新するようなウェブサイトで、いちいちHTMLファイルを作成・更新することは困難だ。最新記事一覧や、おすすめの記事などがある場合は、全ページを手動で更新することがいかに非現実的かがお分かりいただけるだろう。
そこで、ユーザがアクセスしてきたら、必要なデータを収集し、HTMLを生成してユーザに返す技術が必要になってきた。このような「動的なウェブサイト」を構築するために、PHPというプログラミング言語は誕生した。その目的の通り、もっぱらサーバサイドで動作する言語だ。
PHPで動的にHTMLを生成する
WordPressは、動的なウェブサイトを構築するためのソフトウェアである。
ユーザがサーバにアクセスするとPHPプログラムが動き出す。アクセスしてきたページを表示するための情報を集め、処理し、最終的にブラウザで表示できる形式のHTMLを返す(ちなみに、.htmlファイルは生成されず、すべてバーチャルなデータだ)。
ページを表示するためには、そのページに含まれているデータが必要だ。たとえばタイトルや本文、投稿日時などがその例にあたる。このような、ファイルとして実態を持たないデータはデータベースに保存される(WordPressでは、データベースにMySQLを採用している)。
- ユーザがページにアクセス
- PHP処理開始
- PHPがデータベースにアクセスし、必要な情報を収集
- PHPが最終的なHTMLを生成
- ブラウザがHTMLを解釈し、ページを表示
静的なウェブサイトと比べ、アクセスしてから表示するまでにいくつかのプロセスが必要になるため、その分応答までに時間がかかることになる。WordPressサイトを超高速化! 必須プラグインと着実な8つの手順でも述べたが、プラグインを増やすとどんどん処理時間が増える理由が理解できると思う。
テーマ作成に必要なファイルはたった2つしかない
たとえばWordPress標準のテーマを開くと、たくさんのphpファイルやフォルダがある。もちろん最終的にテーマとして仕上げるには相応のファイル数が必要になるのだが、じつはたった2ファイル、style.cssとindex.phpさえあればテーマ作成は可能だ。
理解を深めるため、ここからは実際に手を動かしてやってみてほしい。
まず、WordPressがインストールされているフォルダ内から、wp-content→themesとたどり、新しいテーマ用のフォルダを作る。ここではsampleとしよう。その中に、次のような内容のstyle.cssを作る。
/*
Theme Name: Sample Theme
*/
テーマの名前を入れることで、WordPressが勝手にテーマであることを認識してくれる。とりあえす、他には何も記載しなくていい。
今度は、index.phpを作る。わかりやすくするため次のようなコードを入れておこう。
<?php
echo 'サンプルテーマ';
?>
これで完成した。管理画面からテーマを有効化し、実際にウェブサイトを開くと「サンプルテーマ」と表示されるはずだ。
練習するときは、実際のサーバを使わず、ローカル環境でWordPressを動かした方が楽だ。
ローカル環境で使うにはいくつか方法があるが、Bitnamiを使えばインストーラを叩くだけですむ。
絶対にはずせない、テンプレート階層への理解
WordPressがページを表示するときに使うphpファイルのことを、「テンプレート」という。
たとえば、ユーザが「Web」というカテゴリ(カテゴリIDを4とする)のページにアクセスしてきたとき、WordPressは次のようにテンプレートを探しに行く。
通常、カテゴリごとにレイアウトや表示を変える必要はないので、category.phpを一つ用意しておけばいいだろう。もし特定のカテゴリだけ何か別の処理をしたくなったら、category-$slug.phpやcategory-$id.phpを用意すれば、WordPressが優先的にそのファイルを使ってくれるようになる。
どのファイルも存在しなかった場合、最終的にはかならずindex.phpにたどり着く。index.phpさえあればテーマが動作するのはこのためだ。
テーマを作るときは、この階層構造を理解しておく必要がある。テンプレート階層に概念図がのっているので、しばらく眺めておおまかな構造を把握しておこう。
テンプレートPHPファイルに書けるもの
テンプレート用のPHPファイルには、大別すると次の3つのものを書くことができる。
- HTML
- PHPコード
- WordPressが用意している機能
一つひとつみていこう。
通常のHTMLコード
静的なHTMLファイルを作るときに書くHTMLは(styleタグやscriptタグも含め)、そのまま記述することができる。
<!DOCTYPE html>
<html>
<head>
<title>サンプルページ</title>
</head>
<body>
<p>ただのサンプルページ</p>
</body>
</html>
もちろん、これでは静的なウェブサイトとまったく同じだから、WordPressのメリットを享受することはできない。
PHPコード
phpファイルなのだから、普通のPHPコードを動作させることができる。PHPの処理を動かしたい場合は、<?php /*code*/ ?>
というタグで囲む。
<?php
$output = "現在の日付と時間: ";
$output .= date( DATE_RSS );
echo $output;
?>
実行すると、次のような文字列がブラウザに表示されるはずだ。
現在の日付と時間: Sat, 14 Jan 2017 13:55:17 +0000
「え? PHP勉強しなきゃいけないの?」と戸惑う方もいるかもしれない。残念ながら、WordPressを使いこなすには、ある程度PHPを扱える必要がある。がっつりプログラミングできる必要はなくとも、ちょっとした機能なら自分で書ける程度の力は必要だ。PHP自体は難しい言語ではないので、少し勉強すればだれでも使えるようになる。
WordPressが用意している機能
これもPHPの一部なのだが、WordPressが用意してくれている様々な機能(実際にはグローバル関数や変数)を使うことができる。というより、こっちがメインだ。
たとえば、今どのページにいるのかを判定する、is_home()
や is_single()
などの条件分岐は有名だろう。記事のタイトルが必要になったら、the_title()
、日付はthe_date()
を使って表示することができる。
このような機能はPHP標準ではなく、WordPressが用意してくれているものだ。かなりの量が存在するので、いきなりすべてを把握することは難しい。まずは、テンプレートタグと呼ばれる、テンプレートを作る際に使われる機能から覚えていこう。全部覚えられなくても、「こんな機能がある」というのをなんとなく頭に入れておけば大丈夫だ(ちなみに、関数リファレンスにWordPressで使える関数の一覧が掲載されている)。
テンプレートファイルを作るときは、HTML、PHP、WordPressの機能という3つをうまく扱いながら構築する。
WP_Queryを理解する
通常、WP_Queryは表に出てくることはない。しかし、WP_Queryを理解できると、WordPressをより深く知ることができる。
前述のとおり、記事の内容を表示したり、関連情報を表示したりするには、データベースにアクセスする必要がある。MySQLにアクセスするには、通常SQL文という面倒な記述をしなければならないのだが、WordPressではSQLを意識しなくていいようになっている。その一つが、WP_Queryだ。
クエリとは
そもそもクエリとは何だろうか。ちょっとかわいい名前をしているが、結論から言うと「データベースへの要求」のことだ。
たとえば
- 新着記事を新しい順に3件ほしい
- Webカテゴリの記事が3件ほしい
のような要求をデータベースに出すこと、これがクエリだ。また、クエリするための条件、「新着記事」や「5件」あるいは「Webカテゴリ」などの条件は、クエリ変数と呼ばれる。
WordPressで記事をクエリする
WP_Queryクラス(機能のまとまりだと思えばいい)は、投稿記事に関するクエリ操作を一手に担っている。実際に少し使ってみよう。
<?php
$query = new WP_Query( $args );
?>
使い方はいたってシンプルで、上のように、WP_Queryインスタンスを新たに作成するだけだ(クラスやインスタンスがわからない場合は、ひとまずこういうものだと思ってもらえればいい)。引数$args
には、クエリ変数を格納した配列を渡す。
たとえば、Webカテゴリの記事を3件、という場合は次のようにする(事前に適当な記事を投稿しておこう。カテゴリのslugは管理画面のカテゴリで調べることができる)。
<?php
$args = array(
'category_name' => 'web',
'posts_per_page' => 3
);
$query = new WP_Query( $args );
?>
たったこれだけだ。欲しい投稿記事の条件をクエリ変数に入れるだけで、あらゆる記事を取得することができる。どのようなクエリ変数があるかは、このページに書かれている。
また、$query
には、データベースから取得してきたデータすべてが格納されている。興味のある方は上のコードの最後に、
echo '<pre>';
var_dump( $query );
echo '</pre>';
と記載してみよう。ブラウザで確認すると、中身が出力されているはずだ。
WordPressループとは
これまでの操作で、クエリをして記事を取り出すことには成功したが、内容をブラウザで表示するためには、一つひとつの記事を順番に出力していかなければならない。WordPressでは、これを次のように処理する。
<?php
while( $query->have_posts() ) {
$query->the_post(); //記事をとりだして、$postにセットする
echo $post->post_title . '<br />'; //記事のタイトルを出力
}
?>
while( /*条件*/ )
は、条件を満たす限り繰り返す命令だ。この場合、$query->have_posts()
を条件としているので、記事が存在する限りループして処理が行われる。
次の、$query->the_post();
で記事を一つ取り出して、$post
というグローバル変数に格納する。$post
には、記事一つを表示するためのすべての情報が含まれている。
最後に、$post->post_title;
と書いて、タイトルを表示してみた。本文を表示したい場合は、$post->post_content;
とすればよい。記事を格納している$post
からどのような情報を取り出せるかは、このページに記載されている。
記事を取り出して繰り返していくうちに、最終的には0になり、ループが終了する。この繰り返し処理のことを、一般的にはWordPressループと呼んでいる。
なお、クエリした結果記事が一件もない場合もあるだろう。念のため、このチェックを入れて分岐させておくのが安全だ。
<?php
if( $query->have_posts() ) {
while( $query->have_posts() ) {
$query->the_post();
echo $post->post_title . '</br >';
}
} else {
echo 'お探しの記事は見つかりませんでした。';
}
?>
WordPressの勉強をしたことがある方なら、「なんかいつものループじゃない」と違和感を覚えるかもしれない。実際その通りで、WordPressはこの処理をもう少し単純に書けるよう工夫がなされている。
クエリの自動化と、グローバル関数
WordPressはクエリを自動で行ってくれる
WordPressでは、このクエリを意識せずとも、ウェブサイトを構築できるように設計されている。
- ブログページにアクセス
- WordPressが新着記事を自動的にクエリ
- クエリ結果を
$wp_query;
に格納
カテゴリページでも固定ページでも同じことが行われる。
$wp_query;
は先ほどの$query;
部分に該当するので、$wp_query->have_post();
とすれば記事があるかどうかを判定することができる。
ブログページでは、クエリのステップを飛ばして、次のように書けば記事の一覧を表示できることになる。
<?php
if( $wp_query->have_posts() ) {
while( $wp_query->have_posts() ) {
$wp_query->the_post();
echo $post->post_title . '</br >';
}
} else {
echo 'お探しの記事は見つかりませんでした。';
}
?>
この自動化のおかげで、ぼくらはクエリを明示的に行わなくても、記事一覧を表示することができるわけだ。
一度に何件記事を表示するかは、管理画面の「設定」から「表示設定」を開いたところにある、「1ページに表示する最大投稿数」で決められている。
コードを単純化するためのグローバル関数
いちいち$wp_query
と書くのは面倒なので、この手間を省くためのグローバル関数(WordPress内のどこからでも呼び出せる関数)が用意されている。先ほどのコードを書き直してみよう。
<?php
if( have_posts() ) {
while( have_posts() ) {
the_post(); //記事をひとつ取り出す
the_title(); //タイトルを出力
echo '<br />';
}
} else {
echo 'お探しの記事は見つかりませんでした。';
}
?>
ずいぶんとシンプルになった。ぼくらが$wp_query->the_post();
などとまじめに書かずとも、the_post();
と呼ぶだけで同じことをしてくれる。
ためしにthe_post();
の定義を見てみると
function the_post() {
global $wp_query;
$wp_query->the_post();
}
のようになっていて、中で$wp_query->the_post();
を呼んでいるにすぎないことがわかる。
本文(投稿内容)を表示するにはthe_content();
、投稿日を表示するにはthe_date();
と書けばよい。
何が使えるかは、最初のほうで紹介したテンプレートタグというページに記載されている。ブログに関しては、その中の「投稿タグ」を参照するといいだろう。
テンプレートタグを眺めていると、theからはじまるものと、get_theから始まる似たようなタグがあることに気づく。たいていの場合、theから始まるものは中でechoを呼んでいるので、HTMLとして出力される。get_theは単に文字列を返すだけで、出力はされない。
たとえば、the_title();
は、echo get_the_title();
と同じことになる。
実際にループを書くときは、HTMLのタグでそれぞれの要素を囲みたくなる。<?php /*code*/ ?>
をうまく切り貼りして、HTMLのタグを挿入しよう。
<?php if( have_posts() ) : ?>
<?php while( have_posts() ) : ?>
<?php the_post(); ?>
<h1>
<?php the_title(); ?>
</h1>
<div class="article-content">
<?php the_content(); ?>
</div>
<?php endwhile; ?>
<?php else : ?>
<p>お探しの記事は見つかりませんでした</p>
<?php endif; ?>
ちなみに、ブログページにほかのループ、たとえば人気記事一覧などを表示したい場合には、上で述べた$query = new WP_Query( $args );
でクエリする方法を用いる。
たまにquery_posts();
を使う説明をしているサイトを見かけるが、公式ドキュメントにもある通り、メインクエリを書き換えるうえ非効率的なので、query_posts();
は使ってはならない。
同じような処理はまとめることができる
代表的なものに、header.phpとfooter.phpがある。ヘッダーやフッターは全ページで共通なので、分解して別ファイルにし、何回も同じ処理を書かなくて済むようにするわけだ。
従って、index.phpは次のようになっていることが多い。
<?php get_header(); ?>
ループ処理をここに書く
<?php get_footer(); ?>
共通処理をまとめておけば、後で変更したくなった時も一か所変えるだけですむ。
ヘッダーやフッターに限らず、共通処理はなるべく別のファイルにして一か所にまとめてしまおう。たとえば、ループ処理などがその最たるものだ。よくコピペで解決するサイトを見かけるが、効率が悪く保守が面倒なのでおすすめしない。
ファイルを分けておけば、ループ処理をほかのページ、たとえばcategory.phpでも使いまわすことができる。
自分で作成したphpファイルを読み込むには、次のように書く。
<?php get_template_part( 'loop' ); ?>
「使いまわしたいんだけど、index.phpとcategory.phpで微妙に内容が違う……」というときもあるかもしれない。そんなときは、条件分岐タグの出番だ。
<h1>
<?php
if( is_category() ) {
echo 'カテゴリー:' . get_the_title();
} else {
the_title();
}
?>
</h1>
この例では、カテゴリページのタイトルだけ「カテゴリー:」が頭につくようにしてみた。
ループ以外でも、同じような処理がでてきたら、別のファイルにして共有できるようにしよう。
おわりに
WordPressは一見すると難しそうだが、ポイントを押さえてしまえば自分の思い通り、なんでもできるようになる。プログラミングというハードルが多少あるものの、そこさえ乗り終えてしまえばあとは簡単だ。
コピペに頼らず、WordPress Codexとにらめっこしながら、ぜひ一度自分の手でテーマを作ってみてほしい。使いこなせるようになれば、サイト構築がより一層楽しくなるはずだ。