2026年5月30日

2026年5月30日

WordPressのOptions API・Transients APIの使い分けと実装例

WordPressで設定値のように「ずっと残す値」は Options API、外部APIの応答や重いクエリの結果のように「期限付きで使い回す値」は Transients API で保存するのが基本です。この記事では、両者の違い、get_option() や set_transient() の正しい使い方、autoload の考え方、そしてよくある落とし穴までを、プラグインにそのまま書けるコード例付きで解説します。読み終えるころには、どちらに何を入れるかを判断し、サイトを重くしない保存方法を選べるようになります。

Options APIとTransients APIの違い

どちらもキーと値の組を保存する仕組みですが、前提が異なります。

  • Options API:値は削除するまで残ります。プラグインの設定、サイト全体のフラグ、バージョン番号の記録などに使います。保存先は wp_options テーブルです。
  • Transients API:有効期限を付けて保存する一時キャッシュです。期限が切れると取得時に false が返り、作り直す前提で使います。永続オブジェクトキャッシュ(Redis や Memcached など)が有効な環境では、データベースではなくオブジェクトキャッシュに保存されます。

判断の目安は「消えたら困るか」です。消えると機能が壊れる値は Options、消えても作り直せる値は Transients に入れます。Transients は期限より前に消えることもあるため(キャッシュの追い出しやキャッシュ削除系プラグインの操作など)、「必要な値の保管場所」としては使えません。

コードの置き場所は、独自プラグインか mu-plugin が向いています。テーマを切り替えても動作が続くからです。テーマに密接な設定であれば子テーマの functions.php でも構いません。いずれも、本番に入れる前にバックアップを取り、ステージング環境で動作を確認してください。

Options APIの基本操作

主な関数は次の4つです。

// 取得:存在しない場合は第2引数の既定値が返る
$options = get_option( 'myprefix_options', array() );

// 追加:すでに存在する場合は何もしない
add_option( 'myprefix_db_version', '1.0' );

// 更新:存在しなければ追加される
update_option( 'myprefix_db_version', '1.1' );

// 削除
delete_option( 'myprefix_db_version' );

押さえておきたい点がいくつかあります。

  • 配列はそのまま渡す:配列やオブジェクトは WordPress が自動でシリアライズします。自分で serialize() すると二重になり、扱いにくくなります。
  • 関連する設定は1つの配列にまとめる:項目ごとにオプションを作るとレコードが増えます。1つのプラグインの設定は1つのオプション名に配列でまとめると管理しやすくなります。
  • **update_option() の戻り値**:値が変わらなかった場合も false が返ります。戻り値だけで「保存失敗」と判断すると誤検知になります。
  • 名前には接頭辞を付ける:myprefix_ のような独自の接頭辞で、ほかのプラグインとの衝突を避けます。

管理画面の設定はregister_settingで保存する

設定画面から保存する値は、Settings API の register_setting() で登録すると、nonce の検証と権限チェックを WordPress の仕組みに任せられます。sanitize_callback で入力値を整えてから保存するのが重要です。

add_action( 'admin_init', 'myprefix_register_settings' );
function myprefix_register_settings() {
	register_setting(
		'myprefix_settings_group',
		'myprefix_options',
		array(
			'type'              => 'array',
			'sanitize_callback' => 'myprefix_sanitize_options',
			'default'           => array(
				'api_endpoint' => '',
				'items'        => 5,
			),
		)
	);
}

function myprefix_sanitize_options( $input ) {
	$input = is_array( $input ) ? $input : array();
	return array(
		'api_endpoint' => isset( $input['api_endpoint'] ) ? esc_url_raw( $input['api_endpoint'] ) : '',
		'items'        => isset( $input['items'] ) ? min( 50, max( 1, absint( $input['items'] ) ) ) : 5,
	);
}

フォーム側では settings_fields( 'myprefix_settings_group' ) を出力し、options.php へ送信します。値を画面に表示するときは esc_attr() や esc_html() でエスケープしてください。

autoloadの考え方

wp_options のうち autoload が有効なオプションは、ページ表示のたびにまとめて読み込まれます。頻繁に使う小さな設定には便利ですが、大きなデータや一部の画面でしか使わない値まで autoload にすると、全ページの処理が重くなります。

WordPress 6.6 以降、add_option() と update_option() の autoload 引数は真偽値(true / false)で指定する形が推奨になり、省略した場合は WordPress が判断する仕組みに変わりました(2026年10月現在)。大きすぎる値は既定で autoload されにくくなり、サイトヘルスでも autoload の量が確認できます。それでも、用途が限られる値は明示的に false を指定しておくと意図が明確になります。

// 管理画面の一部でしか使わない大きなデータは autoload しない
update_option( 'myprefix_import_log', $log_array, false );

autoload されている大きなオプションを調べるには、次のようなSQLで目安を確認できます(テーブル接頭辞は環境に合わせてください。実行前にデータベースのバックアップを取ってください)。

SELECT option_name, LENGTH(option_value) AS bytes
FROM wp_options
WHERE autoload IN ('yes', 'on', 'auto-on', 'auto')
ORDER BY bytes DESC
LIMIT 20;

上位に、すでに削除したプラグインの名前が残っていることがよくあります。削除する場合は、そのオプションがどのプラグインのものかを確かめてからにしてください。

Transients APIの基本操作

外部APIの結果を1時間キャッシュする典型的な実装です。

function myprefix_get_remote_items() {
	$cache_key = 'myprefix_remote_items';
	$items     = get_transient( $cache_key );

	if ( false !== $items ) {
		return $items;
	}

	$response = wp_remote_get( 'https://api.example.com/items', array( 'timeout' => 5 ) );

	if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
		// 失敗時は短時間だけ空配列を保存し、API への連続アクセスを避ける
		set_transient( $cache_key, array(), 5 * MINUTE_IN_SECONDS );
		return array();
	}

	$items = json_decode( wp_remote_retrieve_body( $response ), true );
	$items = is_array( $items ) ? $items : array();

	set_transient( $cache_key, $items, HOUR_IN_SECONDS );
	return $items;
}

出力するときは、外部から来た値として esc_html() や esc_url() でエスケープします。

Transientsでつまずきやすい点

  • **false を保存しない**:get_transient() は「存在しない・期限切れ」のときに false を返します。値そのものが false だと区別できないため、空の結果は空配列や 0 で保存します。
  • 期限は「最大」で、保証ではない:期限より前に消えることがあります。消えたら作り直すコードを前提にします。
  • 期限 0 に注意:期限を指定しないと期限なしで保存され、データベース保存時は autoload の対象にもなります。期限は HOUR_IN_SECONDS などの定数で明示しておくと安全です。
  • キー名の長さ:トランジェント名には長さの上限(172文字)があります。URLなどを含める場合は md5() でハッシュ化して短くします。
  • データ更新時に消す:投稿の内容から作るキャッシュなら、save_post などのフックで delete_transient() を呼び、古い表示が残らないようにします。
  • アクセスが集中するサイト:期限切れの瞬間に多数のリクエストが同時に作り直しを始めることがあります。重い処理は WP-Cron で定期的に更新し、表示側は読むだけにする構成も検討してください。

マルチサイトでネットワーク全体に共有したい値は、get_site_option() / update_site_option() や set_site_transient() / get_site_transient() を使います。

WP-CLIで確認・整理する

WP-CLI が使える環境では、保存内容の確認やキャッシュの整理が素早く行えます。

# 自分のプラグインのオプションを一覧
wp option list --search="myprefix_*"

# 値を確認
wp option get myprefix_options --format=json

# 期限切れのトランジェントを削除
wp transient delete --expired

期限切れのトランジェントは WordPress が定期的に掃除しますが、WP-Cron が動いていない環境では溜まることがあります。wp transient delete --all のような一括削除は、ほかのプラグインのキャッシュも消して一時的に負荷が上がるため、アクセスの少ない時間帯に行ってください。

まとめ

  • 消えると困る値は Options API、作り直せる一時データは Transients API に保存します。
  • 設定は接頭辞付きの1つのオプションに配列でまとめ、管理画面の保存は register_setting() と sanitize_callback を使います。
  • autoload は小さく頻繁に使う値だけにし、大きな値は false を明示します。
  • トランジェントには false を保存せず、期限を明示し、期限前に消えても動くコードにします。
  • 永続オブジェクトキャッシュがある環境では、トランジェントの保存先がデータベースではなくなる点を理解しておきます。

お気軽にご相談ください

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