テーマカスタマイザーへ追加したチェックボックスのデフォルト値をtrueにしていて、確かにテーマカスタマイザー上ではチェックが入っているのに、条件分岐を使って処理を切り分けるとfalseとして処理されてしまう現象の改善方法についてのメモ。

この処理がうまくいかなかったのが以下のパターン。WordPress5.8で追加されたブロックベースウィジェットをデフォルトではオフ(無効)にして、任意に使えるようにしようというものです。

/* ブロックペースのウィジェット編集を無効にする */
$wp_customize->add_setting( 'fulledit_widget_disable', array(
	'default' => true,
	'sanitize_callback' => 'habone_sanitize_checkbox',
) );
$wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'fulledit_widget_disable', array(
	'label' => __('Disable Full Edit Widget','habone'),
	'description'=>__('Disables the block-based widget editing feature introduced in WordPress 5.8','habone'),
	'section' => 'default_function_control_section',
	'settings' => 'fulledit_widget_disable',
	'type'=>'checkbox',
	'priority' => 80,
)));

上記コードで「’default’ => true,」にしているので、テーマをインストールした初期状態でカスタマイザー項目を見ると確かにチェックが入っています。

テーマカスタマイザーのチェックボックスで、デフォルト値と条件分岐の判定を確実に同一にする方法|Twenty Twenty-Two (TT2)のカスタマイズ情報

でも、実際のウィジェット設定画面を開くと、下図のようにブロックベースのウィジェットが開くという現象が発生しました。

テーマカスタマイザーのチェックボックスで、デフォルト値と条件分岐の判定を確実に同一にする方法|Twenty Twenty-Two (TT2)のカスタマイズ情報

ブロックベースのウィジェットを無効にするために、functions.phpへ追記したコードが以下。

/***** カスタマイザーにより5.8で追加されたブロックベースのウィジェットを停止 *****/
if(get_theme_mod( 'fulledit_widget_disable') == true){
	add_filter( 'gutenberg_use_widgets_block_editor', '__return_false' );
	add_filter( 'use_widgets_block_editor', '__return_false' );
}

get_theme_modでfulledit_widget_disableがTrueだったら、ブロックベースウィジェットを無効にするフィルターフックが発動するというものです。

この条件判定にはいろいろな書き方があることは知っているのですが、以下の方法でほぼ確実に整合性が取れるようです。

デフォルトでtrueにしたチェックボックスと条件分岐関数の判定を一致させる一番確実かつ簡単な方法

この問題に遭遇した当初は、テーマインストール時にデフォルト値をデータベースのoptionsの該当行へ書き込むようにしたらいいのでは?と考えていろいろ調べましたが、あまり良い文献が見つからず、かつ、「ひょっとしてテーマの更新や再インストールで発火してしまって不都合が発生するかも..」という懸念があり、一時は先送りにしていました。

でもやっぱりチェック済できちんと動作させたい!でいろいろ調べたところ、実に簡単な書き方で正確に判定できるようになります。

このページを見ていらっしゃる方は、当然同じところで躓いていると思うので、結論を紹介する前に、WordPressのカスタマイザーの仕組みがどうなっているのかから順に解説します(不要な方は適当に読み飛ばしてください)。

冒頭で記載したコードのように、テーマカスタマイザーの項目を設定するfunctions.phpなどへの記述で、「’default’ => true,」にした時には、管理画面のテーマカスタマイザー上の見た目にはチェックが入っていますが、これは見た目の話であり、実際にtrue(真)にするためには、一度何かの変更をするなどして「公開」をクリックしなければ反映されません。

今回動作しなかったのは、これが原因で、テーマをインストールした状態(カスタマイザーで「公開」を一度もクリックしていない状態)では、optionsテーブル上のテーマ設定を格納している行(theme_mods_テーマ名)には何も記録されていないため、falseと判定され、カスタマイザー上ではチェックが入っているのに、そのように動作しないということが発生したのです。

これを解消する一番簡単かつ正確な方法は、以下のコード例のように、項目にチェックがあるかないかの条件分岐で、空だったら(データが存在しなかったら)というデフォルト値(true)を第二引数へ設定することです。

if(get_theme_mod( 'カスタマイザーのコントロール名',true)){
true(真)だった場合に処理する内容
}

これで、以下のような動きをするようになります。

  • チェック済項目があり、インストール後何もしていない(公開をクリックしていない)状態では条件分岐関数のデフォルト(第二引数のtrue値)で処理をする
  • チェック済項目があり、この項目以外の何かの項目の変更を行ってテーマカスタマイザーの公開をクリックすれば、チェック済としてデータベースに記録され、Trueで処理をする
  • チェック済項目があり、その項目のチェックを外してテーマカスタマイザーの公開をクリックすれば、未チェックとしてデータベースに記録され、falseで処理をする

また、チェックが入っていない状態というのを処理するときは、

if(get_theme_mod( 'カスタマイザーのコントロール名',true)){
}else{
偽だった場合に処理する内容
}

という風に、PHPに準拠したelseを使った書き方をして、true(真)でなかったらとしておくとより確実に処理されると思います。

本記事を参考に設定を行う際には、optionsテーブルのテーマオプション行(theme_mods_テーマ名)を削除して完全にインストール前にした状態からテストするなど、十分に動作試行を行ってください

なお、このデフォルト設定は、get_optionでも同様に使えるので試してみてください。

本末転倒な考え方ですが、どうしてもうまくいかないときは、「チェックが入っていたら真」ではなく、「チェックが入っていたら偽」として処理する(振舞いを逆にする)とすっきりするかも知れません。

おまけ ユーザー定義関数化しておくと、更に使いやすくなるかも

同じ条件での分岐を複数の場所で使う場合には、ユーザー定義関数(WordPressに任意の関数を追加)しておくと、コードがすっきりするかも知れません。

定義の方法は以下の通りです。

function ユーザー定義関数名(){
  return get_theme_mod( 'カスタマイザーのコントロール名',true);
}

ユーザー定義関数を例えば「is_test_function」にしておくと、実際に条件分岐を行うテンプレートなどで

if(is_test_function()){
true(真)だった場合に処理する内容
}

と書けばよくなります。

また、ユーザー定義関数化しておくと、以下のように関数の先頭に「!」を付ければ

if(!is_test_function()){
チェックが入っている状態の場合の内容
}

逆の意味として使うことが簡単にできるようになります。

本記事を参考に設定を行う際には、optionsテーブルのテーマオプション行(theme_mods_テーマ名)を削除して完全にインストール前にした状態からテストするなど、十分に動作試行を行ってください