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 ページの例では、次の順に最初に見つかったファイルが使われます。
子テーマ/templates/404.twig親テーマ/templates/404.twig子テーマ/404.php親テーマ/404.php子テーマ/templates/index.twig親テーマ/templates/index.twig子テーマ/index.php親テーマ/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 などの代替も比べたうえで選んでください。