get_option の既定値が効かない原因|空文字・false・0 の扱い

結論

  • get_option( $name, $default ) の $default は、オプションがデータベースに存在しないときだけ返ります(公式の記載)。空文字 '' や 0 が保存されていれば、その値が返り、既定値にはなりません。
  • 「空なら既定値」にしたいときは、$value = get_option( 'x' ); if ( '' === $value || false === $value ) { ... } のように、自分で判定します。
  • 値が false かどうかで「存在しない」を判断するのは危険です。false を保存すると、空文字として保存・取得される場合があります。
  • 設定を register_setting() で登録するなら、default 引数で既定値を一元化できます。

原因・仕組み

get_option() は、キャッシュ(alloptions など)を確認し、なければDBを読みます。DBに行がなければ、$default(省略時は false)を返します。行があれば、保存された値を返します。

状態 get_option( 'x', 'D' ) の結果
行がない 'D'
''(空文字)が保存済み ''
false が保存済み 空文字または false(保存方法による)
0 が保存済み 0

特に初心者が詰まるのは、「保存した空文字が既定値に戻らない」ことと、「|| や ?: で 0 を既定値に置き換えてしまう」ことです。

手順(サンプルコード)

「存在しない」と「空」を区別したい場合は、センチネル(目印)値を使います。

// 1) 存在しないときだけ既定値
$limit = get_option( 'myplug_limit', 10 );

// 2) 空文字・0 も「未設定」とみなして既定値にしたい(0 を許可しない場合)
$limit = (int) get_option( 'myplug_limit', 10 );
if ( $limit <= 0 ) {
    $limit = 10;
}

// 3) 0 や false も有効な値として扱いたい → 存在確認にセンチネルを使う
$raw = get_option( 'myplug_flag', '__none__' );
if ( '__none__' === $raw ) {
    // まだ一度も保存されていない
}

設定の既定値を複数箇所に書くと、ズレます。register_setting() の default か、既定値を返す専用の関数にまとめます。

function myplug_get_options() {
    $defaults = array( 'title' => '', 'count' => 10 );
    return wp_parse_args( (array) get_option( 'myplug_opts', array() ), $defaults );
}

動作確認(検証環境と結果)

WordPress 7.1.2(ja)、PHP 8.2.12。php run.php get-option-default.php で確認しました(テスト用のオプションは最後に削除)。

missing, default 'x': string(1) "x"
missing, no default: bool(false)
stored '', default 'x': string(0) ""
stored false, default 'x': bool(false)
stored 0 -> int(0)
?: with 0 -> int(5)
stored true -> bool(true)
missing -> uses sentinel: bool(true)
  • 存在しないオプションは、既定値 'x' が返りました。
  • 空文字 '' を add_option() で保存した場合は、既定値を渡しても '' が返りました。
  • add_option( 't_false', false ) の後、既定値 'x' を渡しても bool(false) が返りました(既定値は使われません)。
  • 0 を保存した場合は int(0) が返りますが、?: で受けると 5 に化けました。
  • 保存したばかりの値の型は、保存時の型のままでした。ただし、別のリクエストでDBから読むと、数値や真偽値は文字列で返る場合があります(レビュー時に別々の実行で確認したところ、0 を保存→次のリクエストで string(1) "0"、true を保存→string(1) "1" でした)。このため (int) や (bool) の変換をしてから使います。

get_option の既定値が効かない原因の注意点

  • 公式は、オプションを初期化せずに false を戻り値として使うのは悪い実践としています。未設定のたびにDBアクセスが発生することがあるためです。有効化時に add_option() で初期値を入れておく方法が安定します。
  • 保存した直後と別リクエストで型が変わりうるため、=== による比較には注意が必要です。
  • pre_option_{$option} フィルターで値を差し替えられるため、他のプラグインが影響している可能性があります。
  • 配列は、一部のキーだけが欠けることがあります。wp_parse_args() で既定値とマージします。

get_option の既定値が効かない原因でよくあるミス

  • get_option( 'x', 'default' ) と書いて、空欄で保存したのに既定値に戻らないと悩む。
  • if ( ! get_option( 'x' ) ) で、0 や空文字を「未設定」にしてしまう。
  • 既定値を、読む箇所ごとに別の値で書いてしまう。
  • 文字列の '0' と整数の 0 を === で比較して、不一致になる。

get_option の既定値が効かない原因のチェックリスト

  • 「存在しない」と「空」を区別する必要があるか決めたか。
  • 既定値の定義は、1箇所にまとまっているか。
  • 数値・真偽値は、読んだ後に型変換しているか。
  • 有効化時に、初期値を add_option() で入れているか。

get_option の既定値が効かない原因のFAQ(よくある質問)

Q. get_option が毎回DBを読むのは遅くないですか?
A. 自動読み込み(autoload)されるオプションは、起動時にまとめて取得されキャッシュされます。サイズの大きな値は autoload を false にします。

Q. get_option と get_site_option の違いは?
A. 後者はマルチサイトのネットワーク全体の設定です(get_site_option() の使い方|説明・引数・注意点)。

Q. 既定値を変えたら、既存のサイトにも反映されますか?
A. 保存済みの値には反映されません。保存されていないサイトだけが新しい既定値になります。

筆者の見解(get_option の既定値が効かない原因)

get_option() の既定値は、「未設定」と「空」を混ぜない設計をする、という前提で使う関数だと考えます。使う側で毎回既定値を書くより、1つの取得関数に包んでしまう方が、後から既定値を変えるときも楽です。

get_option の既定値が効かない原因の関連項目

出典(一次情報)

タイトルとURLをコピーしました