2026年5月29日

2026年5月29日

WordPressのOptions APIを使ったプラグイン設定の保存・取得方法

はじめに

WordPressのOptions APIは、プラグインやテーマの設定値をデータベースのwp_optionsテーブルに保存・取得するための標準的な仕組みです。シリアライズ・アンシリアライズを自動的に処理するため、配列やオブジェクトもそのまま保存できます。本記事では基本的な使い方から、パフォーマンス最適化・バリデーション・アンインストール時のクリーンアップまで解説します。

症状・原因

  • プラグインの設定値(APIキー、機能のON/OFF、カスタムテキストなど)を永続的に保存したい
  • update_option()を使っているが、ページ読み込みのたびにデータベースへクエリが発行されパフォーマンスが気になる
  • プラグインをアンインストールしたときにデータベースに設定値が残ってしまい、サイトが肥大化している

解決手順

ステップ1:get_option/update_option/add_option/delete_optionの基本

<?php
// =====================================================================
// Options API の基本4関数
// =====================================================================

// --- add_option() ---
// オプションが存在しない場合のみ追加する(すでに存在する場合は何もしない)
// 第3引数は廃止済み(空文字を渡す)、第4引数は autoload 設定
add_option( 'my_plugin_version', '1.0.0', '', 'yes' );
add_option( 'my_plugin_api_key', '',      '', 'yes' ); // デフォルトは空文字

// --- get_option() ---
// オプションを取得する。存在しない場合は第2引数のデフォルト値を返す
$version  = get_option( 'my_plugin_version', '1.0.0' );
$api_key  = get_option( 'my_plugin_api_key', '' );
$is_debug = get_option( 'my_plugin_debug_mode', false );

// --- update_option() ---
// オプションを更新する。存在しない場合は自動的に作成する(add_option不要)
// 戻り値: 更新成功でtrue、値に変更がなければfalse
$updated = update_option( 'my_plugin_version', '1.1.0' );
update_option( 'my_plugin_api_key', 'sk-xxxxxxxxxxxxxxxx' );

// autoloadを明示的に指定する(第3引数)
update_option( 'my_plugin_heavy_data', $data, false ); // autoload無効

// --- delete_option() ---
// オプションを完全に削除する
delete_option( 'my_plugin_temp_data' );

// =====================================================================
// 実用例:プラグイン有効化時のデフォルト設定初期化
// =====================================================================
function my_plugin_set_default_options() {
    // 各オプションにデフォルト値を設定(上書きしない)
    $defaults = array(
        'my_plugin_enable_cache'    => true,
        'my_plugin_cache_duration'  => 3600,
        'my_plugin_log_level'       => 'error',
        'my_plugin_email_recipient' => get_option( 'admin_email' ),
    );

    foreach ( $defaults as $key => $value ) {
        add_option( $key, $value );
    }
}
register_activation_hook( __FILE__, 'my_plugin_set_default_options' );

ステップ2:配列をオプション値として保存する

<?php
// =====================================================================
// 配列・複数設定値をまとめて1つのオプションに保存する
// =====================================================================

/**
 * 設定値を1つのオプションとして管理するクラス
 */
class My_Plugin_Settings {

    const OPTION_KEY = 'my_plugin_settings';

    // デフォルト設定値
    private static $defaults = array(
        'enable_feature_a' => true,
        'enable_feature_b' => false,
        'api_key'          => '',
        'cache_duration'   => 3600,
        'log_level'        => 'error',
        'custom_css'       => '',
    );

    /**
     * 全設定値を取得する(デフォルト値とマージ)
     */
    public static function get_all() {
        $saved = get_option( self::OPTION_KEY, array() );
        // array_merge でデフォルト値を保持しつつ保存済み値で上書き
        return array_merge( self::$defaults, (array) $saved );
    }

    /**
     * 特定の設定値を取得する
     *
     * @param string $key     設定キー
     * @param mixed  $default 存在しない場合のデフォルト値
     */
    public static function get( $key, $default = null ) {
        $settings = self::get_all();
        return isset( $settings[ $key ] ) ? $settings[ $key ] : $default;
    }

    /**
     * 設定値を保存する(部分更新対応)
     *
     * @param array $new_values 保存する設定の配列
     */
    public static function update( array $new_values ) {
        $current = self::get_all();
        $updated = array_merge( $current, $new_values );
        return update_option( self::OPTION_KEY, $updated );
    }
}

// 使用例
$settings = My_Plugin_Settings::get_all();
$api_key  = My_Plugin_Settings::get( 'api_key', '' );
My_Plugin_Settings::update( array( 'enable_feature_a' => false ) );

ステップ3:autoloadのパフォーマンス最適化

<?php
// =====================================================================
// autoload の仕組みとパフォーマンス最適化
// =====================================================================

// autoload='yes'(デフォルト):WordPressの起動時に自動的に読み込まれる
// → wp_load_alloptions() でキャッシュに格納されるため、get_option() は追加クエリ不要
// → 頻繁に使うオプションは autoload='yes' が有効

// autoload='no':get_option() が呼ばれた時に初めてクエリが実行される
// → ほとんど使わない大きなデータには autoload='no' を指定してパフォーマンス改善

// 頻繁に使う小さなオプション → autoload=yes(デフォルト)
update_option( 'my_plugin_version',      '1.0.0' );          // autoload=yes
update_option( 'my_plugin_enable_cache', true    );          // autoload=yes

// ほとんど使わない大きなデータ → autoload=no
update_option( 'my_plugin_cached_data',   $large_array, false ); // autoload=no
update_option( 'my_plugin_backup_config', $config_data, false ); // autoload=no

// autoload されているオプション一覧を確認する(デバッグ用)
function my_plugin_check_autoload_options() {
    global $wpdb;
    $autoloaded = $wpdb->get_results(
        "SELECT option_name, LENGTH(option_value) as value_size
         FROM {$wpdb->options}
         WHERE autoload = 'yes'
         ORDER BY value_size DESC
         LIMIT 20"
    );
    foreach ( $autoloaded as $option ) {
        error_log( $option->option_name . ': ' . $option->value_size . ' bytes' );
    }
}

// オブジェクトキャッシュが有効な環境では wp_cache_get/set も活用する
function my_plugin_get_expensive_data() {
    $cache_key   = 'my_plugin_expensive_data';
    $cache_group = 'my_plugin';

    $data = wp_cache_get( $cache_key, $cache_group );
    if ( false === $data ) {
        $data = get_option( 'my_plugin_expensive_data', array() );
        wp_cache_set( $cache_key, $data, $cache_group, 300 ); // 5分キャッシュ
    }
    return $data;
}

ステップ4:register_settingでバリデーションとサニタイズを設定する

<?php
/**
 * Settings API との連携:register_setting でサニタイズコールバックを設定する
 */
add_action( 'admin_init', 'my_plugin_register_settings' );

function my_plugin_register_settings() {
    register_setting(
        'my_plugin_settings_group', // オプショングループ名(settings_fields() で使用)
        'my_plugin_settings',       // オプション名
        array(
            'sanitize_callback' => 'my_plugin_sanitize_settings',
            'default'           => array(
                'enable_feature_a' => true,
                'cache_duration'   => 3600,
                'api_key'          => '',
            ),
        )
    );
}

/**
 * 設定値のサニタイズコールバック
 *
 * @param  array $input フォームから送信された設定値
 * @return array        サニタイズ済みの設定値
 */
function my_plugin_sanitize_settings( $input ) {
    $sanitized = array();

    // チェックボックス(boolean)
    $sanitized['enable_feature_a'] = ! empty( $input['enable_feature_a'] );
    $sanitized['enable_feature_b'] = ! empty( $input['enable_feature_b'] );

    // 数値(正の整数)
    $cache_duration = absint( $input['cache_duration'] );
    $sanitized['cache_duration'] = ( $cache_duration > 0 && $cache_duration <= 86400 )
        ? $cache_duration
        : 3600; // 範囲外の場合はデフォルト値に戻す

    // APIキー(英数字とハイフン・アンダースコアのみ)
    $sanitized['api_key'] = sanitize_text_field( $input['api_key'] );

    // セレクトボックス(許可された値のみ)
    $allowed_levels = array( 'debug', 'info', 'warning', 'error' );
    $sanitized['log_level'] = in_array( $input['log_level'], $allowed_levels, true )
        ? $input['log_level']
        : 'error';

    // バリデーションエラーの追加
    if ( empty( $sanitized['api_key'] ) ) {
        add_settings_error(
            'my_plugin_settings',
            'api_key_empty',
            'APIキーを入力してください。',
            'error'
        );
    }

    return $sanitized;
}

ステップ5:アンインストール時のクリーンアップ処理

<?php
// =====================================================================
// プラグインアンインストール時にオプションを削除する
// =====================================================================

// 方法1: register_uninstall_hook を使う(メインプラグインファイルに記述)
register_uninstall_hook( __FILE__, 'my_plugin_uninstall' );

function my_plugin_uninstall() {
    // プラグインが WP_UNINSTALL_PLUGIN 定数を通じて呼ばれたか確認
    if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
        exit;
    }

    // 単独オプションの削除
    delete_option( 'my_plugin_version' );
    delete_option( 'my_plugin_api_key' );
    delete_option( 'my_plugin_settings' );

    // マルチサイト対応:全サイトのオプションを削除
    if ( is_multisite() ) {
        $sites = get_sites( array( 'number' => 0, 'fields' => 'ids' ) );
        foreach ( $sites as $site_id ) {
            switch_to_blog( $site_id );
            delete_option( 'my_plugin_settings' );
            restore_current_blog();
        }
    }

    // カスタムデータベーステーブルの削除
    global $wpdb;
    $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}my_plugin_logs" );
}

// 方法2: uninstall.php ファイルを使う(推奨)
// プラグインルートに uninstall.php を作成し、以下を記述:
/*
<?php
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}
delete_option( 'my_plugin_settings' );
// ... 追加のクリーンアップ処理
*/

注意事項

  • update_option()はadd_option()不要: update_option()はオプションが存在しない場合も自動的に作成するため、別途add_option()を呼ぶ必要はありません(ただしautoloadを明示したい場合はadd_option()を使用)
  • 大きなデータはautoload無効化: 1KB以上のデータにはupdate_option('key', $val, false)でautoloadを無効にしてください。autoloadデータが多いとWordPressの起動が遅くなります
  • 配列の保存: Options APIはPHPのシリアライズを使って配列を保存します。JSONが必要な場合はwp_json_encode()json_decode()で変換してください
  • マルチサイト: マルチサイト環境ではget_option()はサイトごとの値を返します。ネットワーク全体で共有する場合はget_site_option()を使用してください

まとめ

Options APIのget_option()update_option()delete_option()は、プラグイン設定の永続化に最も手軽で安全な手段です。設定をまとめて1つの配列オプションに保存し、register_setting()でサニタイズを自動化し、uninstall.phpで確実なクリーンアップを実装することがベストプラクティスです。関連記事:WordPress Settings APIで管理画面設定ページを実装する方法

お気軽にご相談ください

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