WordPress でプラグインやテーマ開発するのであれば最低限理解しておきたい WordPress のコアの処理について

ウェブ制作の現場では今でも多くのサイトが WordPress で制作されています。ウェブ制作で「WordPress の開発」や「WordPress のカスタマイズ」というと WordPress のテーマ制作を指すことが一般的です。ですがテーマ開発がメインだと、WordPress のコアの処理にあまり目がいきません。というのもコアの処理を理解していなくても WordPress テーマの制作はある程度できてしまうからです。ですがプラグインを開発したり、カスタマイズが複雑なテーマ制作になると、コアがどのようにリクエストを処理しているかをそれなりに理解している必要があります。ここでは WordPress のコアの処理で最低限理解しておきたいことをまとめています。

WordPress のコアの処理は大雑把に3つに分けられる

WordPress の処理を追いかけるのは難しくありません。WordPress のコアの処理は、WordPress がインストールされたディレクトリにある index.php で読み込まれている、wp-blog-header.php にまとめられています。コードは以下の通りです。

/**
 * Loads the WordPress environment and template.
 *
 * @package WordPress
 */

if ( ! isset( $wp_did_header ) ) {

  $wp_did_header = true;

  // Load the WordPress library.
  require_once __DIR__ . '/wp-load.php';

  // Set up the WordPress query.
  wp();

  // Load the theme template.
  require_once ABSPATH . WPINC . '/template-loader.php';

}

コード内のコメント文にも書かれている通り、

  1. WordPress のライブラリを読み込む。
  2. wp 関数を実行して WordPress のクエリをセットアップする。
  3. テーマのテンプレートを読み込む。

の3つにまとめられます。1. では wp-load.phpwp-config.phpwp-settings.php を読み込んでいきます。そこでは WPWP_Query など、WordPress のコアを構成する各種クラスファイルを読み込んでインスタンス化したり、有効化されているプラグイン、適用されているテーマの functions.php を読み込んだりします。この時点では リクエストURL の解析は行われません。

次の 2. の wp 関数ではリクエスト URL の解析、SQL 文の生成、データベースへの問い合わせが行われ、与えられたリクエスト URL に応じて表示すべき投稿情報が $wp_query->posts にセットされます。

最後の 3. では 2. で解析された結果に応じて、テーマのどのテンプレートを読み込むべきかが決定され、テンプレートがインクルードされます。ここでは $wp_query$post といったグローバル変数にしかるべき値がセットされていて、テーマ開発者はシステム要件やデザインに合わせて適切な出力を行います。

$wp->main では名前の通り WordPress のメイン処理を行う

先ほどの wp-blog-header.php の3つの処理のうち、2番目の wp 関数は wp-includes/functions.php に定義されています。

<?php

function wp( $query_vars = '' ) {
    global $wp, $wp_query, $wp_the_query;

    $wp->main( $query_vars );

    if ( ! isset( $wp_the_query ) ) {
        $wp_the_query = $wp_query;
    }
}

ここでは WP クラスのインスタンスである $wpmain メソッドを呼び出しているだけなので、次はその main メソッドを見ます。

<?php

public function main( $query_args = '' ) {
    $this->init();

    $parsed = $this->parse_request( $query_args );

    $this->send_headers();

    if ( $parsed ) {
        $this->query_posts();
        $this->handle_404();
        $this->register_globals();
    }

    /**
     * Fires once the WordPress environment has been set up.
     *
     * @since 2.1.0
     *
     * @param WP $wp Current WordPress environment instance (passed by reference).
     */
    do_action_ref_array( 'wp', array( &$this ) );
}

ここのコードも簡単に追うことができます。

  1. init でユーザー情報が取得される (init メソッドでは wp_get_current_user が呼び出されているだけ)。
  2. parse_request メソッドで、リクエスト URL をリライトルール $wp_rewrite->rules にマッチさせ、クエリ変数の配列 $wp->query_vars へ変換する。
  3. send_headers メソッドで HTTP ヘッダーが送信される。
  4. query_posts メソッドでは 2. でセットされた $wp->query_vars を引数として WP_Query オブジェクトの query メソッドが実行される。そこではクエリ変数をもとに SQL 文が生成されてデータベースへの問い合わせが行われ、投稿情報が取得される。
  5. リクエストされた URL に対して表示すべきものが何も見つからなかった場合は 404 で処理をする。
  6. 各種グローバル変数(`$posts, $post など) にセットする。

$wp->parse_request は文字列である URL からクエリ変数配列へのデータ変形を行う

$wp->parse_request メソッドでは、まずリクエストURL $_SERVER['REQUEST_URI'] や HTTP GET 変数 $_GET、HTTP POST 変数 $_POST から、ドメインなどが取り除かれて、リクエストパスが抽出されます。

$_SERVER['REQUEST_URI']
$_GET                     =====> $this->request
$_POST

例えば https://yukiyuriweb.com/2018/06/06/introduction-to-wordpress-customize-wordpress-with-action-and-filter-hooks/ という URL の場合、$this->request2018/06/06/introduction-to-wordpress-customize-wordpress-with-action-and-filter-hooks になります。

リクエスト URL からリクエストパス $this->request が抽出されると、次はリライトルール $wp_rewrite->rules との照合が行われます。$wp_rewrite->rules は例えば

<?php

$wp_rewrite->rules = [
  "([0-9]{4})/([0-9]{1,2})/([0-9]{1,2})/([^/]+)(?:/([0-9]+))?/?$" => "index.php?year=$matches[1]&monthnum=$matches[2]&day=$matches[3]&name=$matches[4]&page=$matches[5]",
  ...
];

のように、正規表現をキー、正規表現でマッチした場合にサブパターンを抜き出すためのクエリを値とする連想配列になっています。先ほどの URL はこの正規表現にマッチし、parse_str 関数によって配列 $wp->query_vars へと変換されます。

<?php

$wp->query_vars = [
  'page' => '0',
  'year' => '2018',
  'monthnum' => '06',
  'day' => '06',
  'name' => 'introduction-to-wordpress-customize-wordpress-with-action-and-filter-hooks',
];

ここまでをまとめると、$wp->parse_request メソッドでは

$_SERVER['REQUEST_URI'] ==> $wp->request ==> $wp->matched_query ==> $wp->query_vars

というように文字列から配列へとデータが変換されます。この過程で $wp オブジェクトには

  • $wp->public_query_vars: WordPress が処理できるパブリックなクエリ変数(page, year, monthnum, day, name など)の一覧
  • $wp->private_query_vars: WordPress が処理できるプライベートなクエリ変数の一覧
  • $wp->request: 現在のリクエストパス
  • $wp->query_vars: 現在のリクエストに含まれるクエリ変数とその値
  • $wp->matched_rule: $wp_rewrite->rules にあるリライトルールの中で、リクエストURIにマッチしたルール

などの情報がセットされます。

$wp->query_posts ではクエリ変数配列から SQL 文が生成されデータベースへの問い合わせが行われる

$wp->query_posts では WP_Query クラスのインスタンスである $wp_the_query オブジェクトの query メソッドが呼び出されます。

<?php

public function query_posts() {
    global $wp_the_query;
    $this->build_query_string();
    $wp_the_query->query( $this->query_vars );
}

このとき、$wp->parse_request 内でリクエスト URL から抽出されたクエリ配列 $wp->query_vars が引数に渡されます。$wp_the_query->query

<?php

public function query( $query ) {
    $this->init();
    $this->query      = wp_parse_args( $query );
    $this->query_vars = $this->query;
    return $this->get_posts();
}

のようになっており、 $wp_the_query->get_posts が呼びされます。$wp_the_query->get_posts では $wp->query_vars を元にデータベースへクエリするための SQL 文が生成されます。生成された SQL 文は $wp_the_query->request に格納されます。例えば先ほど例に出した URL の場合は次のような SQL 文になります。

SELECT wp_posts.*
FROM wp_posts WHERE 1=1
AND ( ( YEAR( wp_posts.post_date ) = 2018 AND MONTH( wp_posts.post_date ) = 6 AND DAYOFMONTH( wp_posts.post_date ) = 6 ) )
AND wp_posts.post_name = 'introduction-to-wordpress-customize-wordpress-with-action-and-filter-hooks'
AND wp_posts.post_type = 'post'
ORDER BY wp_posts.post_date DESC

SQL 文が生成されると $wpdb を通してデータベースへクエリが投げられ、投稿情報が MySQL から返ってきて $wp_the_query->postsWP_Post オブジェクトの配列として格納されます。

<?php

$this->posts = $wpdb->get_results( $this->request );

WP_Post の配列になった $wp_the_query->posts はテーマ開発者にとって馴染みの深いものです。これは $wp_the_query->have_posts メソッドで表示すべき投稿があるかを判定したり、$wp_the_query->the_post メソッドでグローバル変数の $post に投稿情報をセットしたりします。

以上の処理をまとめると、最初は文字列だったリクエスト URL $_SERVER['REQUEST_URI']$wp->request$wp->matched_query を経て連想配列 $wp->query_vars になり、それが再び文字列である SQL 文 $wp_the_query->request に変換されて、最後に WP_Post の配列である $wp_the_query->posts となってテーマのテンプレートで利用できる形になります。

$_SERVER['REQUEST_URI'] ==> $wp->request ==> $wp->matched_query ==> $wp->query_vars ==> $wp_the_query->request ==> $wp_the_query->posts

まとめ

ここでは WordPress で最低限知っておきたいコアの処理をざっと追いかけました。ここまでを追えることができれば、ブラウザに入力された URL がデータベースに保存されている投稿情報へとどのように変換されていくかが分かると思います。こうしたコアの処理の流れを理解していると、テーマやプラグインを開発する際にどこで処理を追加するべきなのかが見えてくるようになり、WordPress のカスタマイズの幅が広がってくると思います。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です