WordPressのコアファイルを読みながら、PHPを学習してみることにしました(wp-config.phpまで)

html-wireframing-sketch
photo credit: NathanaelB via photopin cc
Update Web制作メモ >

WordPressのテーマファイルではPHPのコードをたくさん使用していますが、意味をあまり理解できていませんでした。デフォルトテーマを参照したり、他の方が公開されているサンプルを参照したりしてただ埋め込んだ!という感じでテーマを作成してしまったためです。

そろそろPHPをちゃんとお勉強しようかなと思い、改めて自作したテンプレートファイルを眺めてみると、PHPの公式リファレンスには載っていない、WordPressだけで使えるテンプレートタグ< と呼ばれるものをたくさん使っているんですよね。

でも、このテンプレートタグのそれぞれの用途をただおさらいするだけではPHPのお勉強にはちょっと足りないかなあと考え、どうしてWordPressではテンプレートタグっていうものが使えるんだろう?ということを調べ始めてみました。これがけっこうPHPのいい学習材料になりそうなので、ここにメモを残すことにしました。

WordPressの関数はコアファイルで定義されているみたい

WordPressのテンプレートタグの例を書いておきます。

テーマを作るときにはおなじみのインクルードタグや、

<?php get_header(); ?>
<!-- header.phpを呼び出す -->

ページごとのカスタマイズをするときに使うis_home()などを用いた条件分岐タグなど(以下は、このブログのぱんくずリストに関するコードです)。

<?php if(is_home()): ?><!-- メインページでは何もしない -->
<?php else: ?><!-- 他のページではぱんくずを表示 -->
    <div class="breadcrumbs">
    <!-- 省略 -->
    </div>
<?php endif; ?>

とっても当たり前なのですが、<php ?>という書き方はWordPressに限ったものではなくて、ふつうのPHPの開始タグと終了タグですよね。

それから、ぱんくずのコードで使っているifelseなども当然、WordPress独自のものではありません。

get_header()とかis_home()といった部分がWordPress独自の関数で、これらをあわせてテンプレートタグと呼ぶみたいです。

このget_header()という関数をWordPress Codex 日本語版ページでを検索してみると、ページの下部にこう書いてありました。

get_header() is located in wp-includes/general-template.php.

is_home() も同様に検索してみました。

is_home() は wp-includes/query.php に含まれています。

どうやら、WordPressをインストールしたときに含まれているコアファイル(普段いじらないファイル)でそれぞれの関数が定義されているようです。

WordPressフォルダ内のコアファイルなどなど。wp-content内にはおなじみのテーマファイルが入っていますが、他のファイルやフォルダはほとんどさわったことがありません。

wordpress folder 400x246

wp-includes/query.phpを見てみると、こんな記述がありました。

function is_home() {
	global $wp_query;

	if ( ! isset( $wp_query ) ) {
		_doing_it_wrong( __FUNCTION__, __( 'Conditional query tags do not work before the query is run. Before then, they always return false.' ), '3.1' );
		return false;
	}

	return $wp_query->is_home();
}

ここでis_home() という関数が定義されているのですね。さらに、そのコード内で使われている$wp_queryという変数はまた別のファイルで定義されていて、さらにそこで使われている関数が別のコアファイルで定義されていて…。

テンプレートタグの仕組みについてわかったことまとめ

ざっくりとまとめてしまいます。

  • WordPress関数は、いくつかの(あるいはひとつの)コアファイルで定義されている
  • コアファイルにあれこれ難しいことが書いてあるおかげで、普段使っているテンプレートファイル内ではis_home() というさっぱりした関数を書くだけですむ!
  • WordPress関数を<php ?>などのPHPコードタグといっしょに書いたものをテンプレートタグと呼ぶ

WordPressの実行フローにそってコアファイルをのぞいてみる

こちらの記事に、とってもわかりやすいフローが書かれています。

このフローによると、WordPressで作成されたページにアクセスがあったときの流れは、こういった感じみたいです。

  • まず、コアファイルのほうの(ページで使われているテーマのファイルではなくて)index.phpがはじめに読み込まれる
  • index.phpから、ファイル内の指示に従ってたくさんのコアファイルが順番に読み込まれる
  • その過程で、さきほどのWordPress関数が読み込まれたり、データベース(MySQL)から記事の文書情報が読み込まれたりなどなどする
  • テーマテンプレートファイルが読み込まれる
  • ブラウザにページが表示される!

そこで、この実行フローを参考にしてコアファイルindex.phpから順番にのぞき、わからないところをPHP公式リファレンスで調べながら解読しながら、テンプレートタグが使えるようになるまでの流れを追ってみることにしました。気の遠くなるようなチャレンジですが。

index.phpはフロント係

WordPressフォルダ直下のindex.phpのなかみです。

<?php
/**
 * Front to the WordPress application. This file doesn't do anything, but loads
 * wp-blog-header.php which does and tells WordPress to load the theme.
 *
 * @package WordPress
 */

/**
 * Tells WordPress to load the WordPress theme and output it.
 *
 * @var bool
 */
define('WP_USE_THEMES', true);

/** Loads the WordPress Environment and Template */
require('./wp-blog-header.php');

「このファイルはフロントです。何もしません。でもwp-blog-header.phpを読み込みます」というようなコメントがあり、そのあとに、ふたつのPHPのコードが書かれています。

さっそく知らない記述が出てきましたので、PHP公式リファレンスで調べました。

  • define - 名前を指定して定数を定義する
  • require - 指定されたファイルを読み込み、評価します

index.phpの役割まとめ

  • WP_USE_THEMESという定数を定義(たぶんあとで使われる)
  • wp-blog-header.phpを読み込む

そんなわけで、次はwp-blog-header.phpです。

環境とテンプレートを読み込むwp-blog-header.php

<?php
/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */

if ( !isset($wp_did_header) ) {
	$wp_did_header = true;
	require_once( dirname(__FILE__) . '/wp-load.php' );
	wp();
	require_once( ABSPATH . WPINC . '/template-loader.php' );
}

「WordPressの環境とテンプレートを読み込みます」というコメントがありました。以下、PHP公式リファレンスより。

  • isset - 変数がセットされていること、そして NULL でないことを検査する
  • ! $a - 否定。$a が TRUE でない場合 TRUE
  • require_once - require とほぼ同じ意味ですが…(省略)
  • dirname - 親ディレクトリのパスを返す
  • __FILE__ - ファイルのフルパスとファイル名。インクルードされるファイルの 中で使用された場合、インクルードされるファイルの名前が返されます

2013.5.20追記

Twitterにて(@donuzium)さんより補足のコメントをいただきました。

ちなみにrequire_onceは一度だけ読みにいくので、DB接続とか複数回実行したくないような処理があったりする場合に使いますね。

ありがとうございます!

wp-blog-header.phpの役割まとめ

  • 変数$wp_did_headerというものがセットされていなければ(WordPressフォルダ直下の?)wp-load.phpを読み込む
  • wp();という関数を実行する ※
  • ABSPATH、WPINCがというものがまだ定義されていないのでよくわからないけれど、とにかくどこかのディレクトリのtemplate-loader.phpを読み込む

さきほどの実行フローによると、wp-load.phpからたどっていったところに、いろんな関数が定義されたりデータベースが読み込まれたりして、template-loader.phpからたどっていったところに、テーマを読み込む何かがあるみたいです。

※ お話が前後してしまうのですが、WordPress Codexのクエリ概要というページで実行フローの詳細が解説されてます。それによるとこのwp();という関数はとても重要みたいです。読んでもまだよくわからないのですが、とにかくここでWordPressにとってとても重要な関数が実行されるみたい。

まずは関数についてのファイルを追っていきたいので、次はwp-load.phpです。

定数ABSPATHなどを定義するwp-load.php

<?php
/*コメント省略*/

define( 'ABSPATH', dirname(__FILE__) . '/' );

if ( file_exists( ABSPATH . 'wp-config.php') ) {
    require_once( ABSPATH . 'wp-config.php' );

/*wp-config.phpが無かった場合についての記述省略*/

define( 'WPINC', 'wp-includes' );
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
require_once( ABSPATH . WPINC . '/load.php' );
require_once( ABSPATH . WPINC . '/version.php' );

wp_check_php_mysql_versions();
wp_load_translations_early();

require_once( ABSPATH . WPINC . '/functions.php' );

/*エラーメッセージを表示させる記述省略*/

記述がずいぶん長くなっていますので、一部を省略しています。冒頭のコメントには「ABSPATHという定数を定義します。そしてwp-config.phpを読み込みます。もしwp-config.phpが無かったら…」というようなことが書かれていました。

wp-load.phpの役割まとめ

  • さきほど登場した定数ABSPATHを定義。要するにABSPATHっていうのは、このwp-load.phpがある場所っていうことで良いのでしょうか。
  • wp-config.phpがあれば読み込む。他の場所にある場合や、無い場合の処理も書いてある。
  • 同じく定数WPINCを定義。WPINCって書いたらwp-includesフォルダ内を指すということ?
  • まだ登場していない定数WP_CONTENT_DIRを定義。
  • load.phpversion.phpを読み込む。
  • ふたつの関数を実行する。関数名からたぶん、データベースのバージョンをチェック、翻訳ファイルを読み込むということかな。
  • functions.phpを読み込む。

4つのファイルを読み込むようですが、実行フローに直接関係するのはwp-config.phpみたいなので、次はwp-config.phpです。

データベースに関する定数を定義したりするwp-config.php

<?php define('WP_CACHE', true);
/** 
 * このファイルは、MySQL、テーブル接頭辞、秘密鍵、言語、ABSPATH の設定を含みます。
 * (以下省略)
 */

// ** MySQL 設定 - こちらの情報はホスティング先から入手してください。 ** //
/** WordPress のデータベース名 */
define('DB_NAME', '***');
/** MySQL のユーザー名 */
define('DB_USER', '***');
/** MySQL のパスワード */
define('DB_PASSWORD', '***');
/** MySQL のホスト名 (ほとんどの場合変更する必要はありません。) */
define('DB_HOST', '***');
/** データベーステーブルのキャラクターセット (ほとんどの場合変更する必要はありません。) */
define('DB_CHARSET', 'utf8');
/** データベースの照合順序 (ほとんどの場合変更する必要はありません。) */
define('DB_COLLATE', '');

/**
 * 認証用ユニークキー
 * それぞれを異なるユニーク (一意) な文字列に変更してください。
 * (以下省略)
 */
define('AUTH_KEY', '***');
define('SECURE_AUTH_KEY', '***');
define('LOGGED_IN_KEY', '***');
define('NONCE_KEY', '***');

/**
 * WordPress データベーステーブルの接頭辞
 * (以下省略)
 */
$table_prefix  = 'wp1_';

/**
 * ローカル言語 - このパッケージでは初期値として 'ja' (日本語 UTF-8) が設定されています。
 * (以下省略)
 */
define ('WPLANG', 'ja');

// 編集が必要なのはここまでです ! WordPress でブログをお楽しみください。

/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
	define('ABSPATH', dirname(__FILE__) . '/');

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

このファイルは、WordPressをローカルにインストールしたときにちょっとだけ触ったので、見覚えがあります。言われたとおりに'***'の中身を書き換えただけでしたが。

wp-config.phpの役割まとめ

  • データベースに関するいろいろな定数を定義。
  • 文字コードをUTF-8に、ローカル言語を日本語に設定。
  • WordPress データベーステーブルの接頭辞というのが何かはわからないのですが、変数$table_prefixを定義。
  • 先ほどのABSPATHが定義されていないければ、ここで定義。
  • wp-settings.phpを読み込む。

ここで読み込まれるwp-settings.phpでいよいよ、最初に挙げたWordPress関数に関わるファイルが読み込まれたりするようですが、今日のメモはここまで。

この作業、置き手紙をたどって宝物をさがすゲーム(伝わるかなあ)みたいで楽しいです。PHPが少しでも身につくといいなあと思っています。