2026年8月12日

2026年8月12日

Clarkson CoreでWordPressテーマをTwig開発する方法:導入・テンプレート・オブジェクト

Clarkson Core(クラークソン・コア)は、オランダの制作会社 Level Level が公開している WordPress 用のライブラリです。テーマのテンプレートを PHP ではなく Twig で書けるようにし、投稿・ターム・ユーザーを PHP のオブジェクト として扱えるようにします。WordPress のテンプレート階層はそのまま使えるので、single.php の代わりに templates/single.twig を置く、という感覚で開発できます。

この記事では、Composer での導入から、Twig テンプレートの置き方、投稿タイプ別のクラス、本番環境での注意点までを順に説明します。手順は WordPress 6.9.4・PHP 8.3・Clarkson Core 1.9.1・Twig 3.30 の検証環境で実際に動かして確認しました(2026年10月時点)。

導入前に知っておくこと

  • 保守のみの状態: 公式リポジトリの README には、新機能の追加は終了し、PHP と WordPress の互換対応だけを続けると書かれています(2026年10月時点の最新は 2026年9月公開の 1.9.1)。これから新しく作るテーマで Twig を使いたい場合は、README でも代替として挙げられている Timber も比べてください。既に Clarkson Core を使っているテーマの保守や改修には、この記事の内容がそのまま使えます。
  • 必要な環境: 1.9.1 の composer.json では PHP 7.4 以上と Twig 3 系が必要です。Composer が使えることも前提になります。
  • クラシックテーマ向け: Twig テンプレートを WordPress のテンプレート階層に差し込む仕組みなので、ブロックテーマ(サイトエディターで編集する HTML テンプレート)とは別の作り方になります。

テーマで Composer を使う方法は「WordPressテーマでComposerを使う」、テンプレートエンジンの比較は「Mustache・Twig・Bladeのテンプレートエンジン比較」も参考にしてください。

手順1: テーマの雛形を作って Clarkson Core を入れる

最終的なファイル構成は次のとおりです。

wp-content/themes/my-clarkson-theme/
├── style.css
├── index.php
├── functions.php
├── composer.json
├── app/
│   └── WordPress_Objects/
│       └── event.php
└── templates/
    ├── layouts/
    │   └── base.twig
    ├── partials/
    │   └── teaser.twig
    ├── archive.twig
    ├── front-page.twig
    ├── single-event.twig
    └── singular.twig

style.css にはテーマ名とバージョンを書きます。バージョンは後で説明する Twig のキャッシュにも使われます。

/*
Theme Name: My Clarkson Theme
Version: 1.0.0
Requires PHP: 7.4
*/

WordPress はテーマとして認識するために index.php を必要とします。中身は空で構いません(表示は templates/ の Twig が担当します)。

<?php
// Clarkson Core が templates/ の .twig を優先して読み込む。

テーマのフォルダーに composer.json を置きます。config.platform.php には本番サーバーの PHP バージョンを書いてください。

{
    "require": {
        "level-level/clarkson-core": "^1.9"
    },
    "autoload": {
        "psr-4": {
            "Clarkson_Core\\WordPress_Object\\": "app/WordPress_Objects/"
        }
    },
    "config": {
        "platform": {
            "php": "8.3"
        }
    }
}
cd wp-content/themes/my-clarkson-theme
composer install --no-dev

config.platform.php を書かずに、手元の新しい PHP(例: 8.4)で composer install すると、依存ライブラリがその PHP 向けの版で入ることがあります。検証では、PHP 8.4 の環境で入れた vendor/ を PHP 8.3 のサーバーで読み込んだところ、「Composer detected issues in your platform」という致命的エラーで画面が表示されなくなりました。手元と本番の PHP が違う場合は、この設定を入れてから composer.lock を作り直してください。

手順2: functions.php で autoload を読み込む

Clarkson Core は Composer の autoload を読み込んだ時点で初期化され、WordPress の init で動き始めます。プラグインとして有効化する操作は要りません。

<?php
// Composer の autoload を読み込む(Clarkson Core 本体もここで初期化される)。
$autoload = get_template_directory() . '/vendor/autoload.php';
if ( file_exists( $autoload ) ) {
	require_once $autoload;
}

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

add_action( 'wp_enqueue_scripts', function () {
	wp_enqueue_style(
		'my-clarkson-theme',
		get_stylesheet_uri(),
		array(),
		wp_get_theme()->get( 'Version' )
	);
} );

title-tag を有効にしておくと、<title> は wp_head() が出力します。テンプレートに <title> を直接書く必要はありません。

テーマを有効化する前に vendor/ があるか確認してください。vendor/ をサーバーに置き忘れると Twig テンプレートが使われず、空の index.php が表示されて真っ白な画面になります。

手順3: templates フォルダーに Twig テンプレートを置く

Clarkson Core は、有効なテーマ(子テーマを使っている場合は子テーマと親テーマ)の templates/ フォルダーから、WordPress のテンプレート階層と同じ順番でファイルを探します。公式ドキュメントにある 404 ページの例では、次の順に最初に見つかったファイルが使われます。

  1. 子テーマ/templates/404.twig
  2. 親テーマ/templates/404.twig
  3. 子テーマ/404.php
  4. 親テーマ/404.php
  5. 子テーマ/templates/index.twig
  6. 親テーマ/templates/index.twig
  7. 子テーマ/index.php
  8. 親テーマ/index.php

つまり、同じ階層では Twig が PHP より優先されます。テンプレート階層そのものは「WordPressのテンプレート階層」で確認できます。

共通レイアウト

templates/layouts/base.twig にページの外枠を書き、各テンプレートは extends で継承します。language_attributes()・body_class()・wp_head()・wp_footer() などは、Clarkson Core が Twig から呼べる関数として登録しています。

<!doctype html>
<html {{ language_attributes() }}>
<head>
	<meta charset="{{ get_bloginfo('charset') }}">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	{{ wp_head() }}
</head>
<body {{ body_class() }}>
	<header class="site-header">
		<a href="{{ home_url('/') }}">{{ get_bloginfo('name') }}</a>
	</header>

	<main class="site-main">
		{% block content %}{% endblock %}
	</main>

	{{ wp_footer() }}
</body>
</html>

個別ページと一覧ページ

個別ページ(singular.twig、single-*.twig など)では、表示中の投稿が object という変数に入っています。

{% extends "layouts/base.twig" %}

{% block content %}
	<article>
		<h1>{{ object.get_title() }}</h1>
		<div class="entry-content">
			{{ object.get_content()|raw }}
		</div>
	</article>
{% endblock %}

一覧ページ(archive.twig など)では、クエリの結果が objects に配列で入ります。

{% extends "layouts/base.twig" %}

{% block content %}
	{% for item in objects %}
		{% include "partials/teaser.twig" with { item: item } %}
	{% else %}
		<p>記事が見つかりませんでした。</p>
	{% endfor %}
{% endblock %}

templates/partials/teaser.twig:

<article class="teaser">
	<h2><a href="{{ item.get_permalink() }}">{{ item.get_title() }}</a></h2>
	<div class="excerpt">{{ item.get_excerpt()|raw }}</div>
</article>

Twig は出力を自動でエスケープします。本文(get_content())と抜粋(get_excerpt())は WordPress のフィルターを通した HTML が返るため |raw を付けます。付けないと <p> などのタグが文字のまま表示されます。題名や URL には |raw を付けないでください。

ほかに、検索結果(search.twig)では found_posts、タクソノミーのアーカイブでは term、投稿者アーカイブでは author といった変数も使えます。WP_DEBUG が有効なときは、{{ dump(object) }} で中身を確認できます。

固定ページのテンプレート

templates/ の中に template-*.twig(例: template-contact.twig)という名前で置いたファイルは、固定ページ編集画面のテンプレート選択に自動で追加されます。

手順4: 投稿タイプごとのクラスで処理をまとめる

Clarkson Core は、投稿タイプ名と同じ名前のクラスが Clarkson_Core\WordPress_Object 名前空間にあれば、その投稿をそのクラスのオブジェクトとして渡します。手順1の composer.json で、この名前空間を app/WordPress_Objects/ に割り当てています。

例として、投稿タイプ event を登録し(functions.php に追記)、開催日を表示用に整えるメソッドを持たせます。

<?php
add_action( 'init', function () {
	register_post_type( 'event', array(
		'label'       => 'イベント',
		'public'      => true,
		'has_archive' => true,
		'supports'    => array( 'title', 'editor', 'thumbnail', 'custom-fields' ),
	) );
} );

app/WordPress_Objects/event.php(ファイル名はクラス名と同じ小文字):

<?php
namespace Clarkson_Core\WordPress_Object;

class event extends Clarkson_Object {
	public static $type = 'event';

	/**
	 * カスタムフィールド event_date(例: 2026-12-01)を表示用に整える。
	 */
	public function get_event_date_label(): string {
		$raw = (string) $this->get_meta( 'event_date', true );
		if ( '' === $raw ) {
			return '';
		}
		$date = date_create_immutable( $raw, wp_timezone() );
		return $date ? wp_date( 'Y年n月j日', $date->getTimestamp() ) : '';
	}
}

クラスを追加・改名したら、Composer の autoload を作り直します。

composer dump-autoload

templates/single-event.twig では、追加したメソッドをそのまま呼べます。

{% extends "layouts/base.twig" %}

{% block content %}
	<article class="event">
		<h1>{{ object.get_title() }}</h1>
		{% if object.get_event_date_label() %}
			<p class="event-date">開催日: {{ object.get_event_date_label() }}</p>
		{% endif %}
		<div class="entry-content">
			{{ object.get_content()|raw }}
		</div>
	</article>
{% endblock %}

投稿タイプ名にハイフンなど PHP のクラス名に使えない文字が含まれる場合、Clarkson Core は小文字にしたうえで英数字以外を _ に置き換えた名前でクラスを探します(例: Example-PostType → example_posttype)。全投稿タイプ共通のメソッドを持たせたいときは、base_object という名前のクラスを作って Clarkson_Object を継承させ、各投稿タイプのクラスは base_object を継承する形にします。

手順5: テンプレートに独自の変数を渡す

テンプレートで使う変数を増やすには、clarkson_core_template_context フィルターを使います。次の例は、フロントページに「イベント3件」を渡します。get_many() は投稿タイプのクラスに用意されている静的メソッドで、WP_Query の引数を受け取り、結果をオブジェクトの配列で返します。

<?php
add_filter( 'clarkson_core_template_context', function ( $context, $wp_query ) {
	if ( $wp_query->is_front_page() ) {
		$context['upcoming_events'] = \Clarkson_Core\WordPress_Object\event::get_many( array(
			'posts_per_page' => 3,
		) );
	}
	return $context;
}, 10, 2 );

templates/front-page.twig:

{% extends "layouts/base.twig" %}

{% block content %}
	<section class="upcoming-events">
		<h2>直近のイベント</h2>
		{% for item in upcoming_events %}
			{% include "partials/teaser.twig" with { item: item } %}
		{% else %}
			<p>予定されているイベントはありません。</p>
		{% endfor %}
	</section>
{% endblock %}

1件だけ取得するときは event::get_one( $args )、ID を指定するときは event::get( $id ) が使えます。

Twig から使いたい PHP 関数が登録されていない場合は、clarkson_twig_function フィルターで追加できます。ウィジェットや管理画面など、テンプレート階層の外で Twig ファイルを表示したいときは \Clarkson_Core\Templates::get_instance()->echo_twig( 'ファイル名.twig', 変数の配列, true ) を使います。

本番環境での注意点

項目 内容
Twig のキャッシュ wp_get_environment_type() が production(初期値)のとき、Clarkson Core はコンパイル済みテンプレートを一時フォルダーの cache/twig/テーマのバージョン/ に保存します。テンプレートを更新したら style.css の Version を上げてください。上げないと古い表示が残ることがあります。保存先は clarkson_twig_args フィルターで変えられます
開発環境 wp-config.php で define( 'WP_ENVIRONMENT_TYPE', 'local' ); などにするとキャッシュが使われず、編集がすぐ反映されます。WP_DEBUG を有効にすると dump() が使えます
vendor の配置 サーバーで composer install --no-dev を実行するか、手元で作った vendor/ を一緒にアップロードします。手元と本番の PHP バージョンは config.platform.php で合わせます
子テーマ 親テーマの templates/ にある Twig は、子テーマの templates/ に同じ名前のファイルを置くと上書きできます

まとめ

  • Clarkson Core は Composer で入れ、テーマの functions.php で vendor/autoload.php を読み込むだけで動きます。
  • templates/ に置いた .twig は、WordPress のテンプレート階層に沿って同名の .php より優先されます。個別ページは object、一覧は objects で投稿を受け取ります。
  • 投稿タイプ名のクラスを Clarkson_Core\WordPress_Object 名前空間に作ると、投稿ごとの処理をメソッドとしてまとめられます。
  • 2026年10月時点で保守のみの状態なので、新しく作るテーマでは Timber などの代替も比べたうえで選んでください。

参考: Clarkson Core(GitHub)、Getting started ガイド

お気軽にご相談ください

お見積りへ お問い合わせへ
▲