WordPress Customizerのsanitize_callbackは設定画面の入力形式ごとに決める
公開日: 執筆:佐藤
WordPress Customizerへ設定項目を追加するときは、表示するinputの種類と、保存してよい値を分けます。sanitize_callbackは、設定値を保存する前に処理するcallbackです。text inputだから文字列をそのまま保存してよい、color pickerだから任意の文字列を保存してよい、とは決まりません。URL、色、数値、選択肢ごとに、受け付ける値を決めます。
Customizerは、管理画面で見た目を変えられる仕組みです。しかし、入力欄を追加することと、誰でも自由に値を変えられるようにすることは同じではありません。headerのリンク先、背景色、表示件数のように公開画面へ影響する値は、何を入力できるか、空欄ならどうするか、どのtemplateで使うかまで決めて初めて設定項目になります。設定を増やす前に、変更を受ける範囲を狭く決めます。
WordPress 4.5のWP_Customize_Setting sourceは、settingへsanitize_callbackを指定できること、保存前の値をsanitize()で扱うことを確認できます。callbackが指定されている場合は、そのcallbackへ値が渡されます。指定がない場合は、そのsettingのsanitize filterが適用されます。Customizerのcontrolは入力画面を出す部品であり、保存する値の形式を決める処理とは別です。
Customizerでは入力画面と保存してよい値を分ける
Customizerのsettingには、site側が保存して使う値が残ります。設定画面に入力欄を出すことと、値を検査して保存することは同じ作業ではありません。controlのtypeがurlなら、利用者へURL用の入力欄を見せられます。ただし、それだけでsettingに保存する値の条件が定義されるわけではありません。入力の見え方はcontrol、保存時の値の扱いはsettingで考えます。
| 設定したい内容 | 入力画面の例 | 保存前に確認すること |
|---|---|---|
| link先URL | text input | URLとして使える形式か |
| 色 | color control | 許可するcolor formatか |
| 表示件数 | number input | 数値か、許可する最小値と最大値に収まるか |
| layoutの選択 | select | 用意した選択肢の一つか |
| 見出し文 | text input | 文字列として必要な処理をした値か |
たとえば、headerのbutton URLを設定できるようにする場合を考えます。画面へtext inputを置くだけでは、その値がlinkのhrefへ使えるか決まりません。空欄を許可するか、site内だけを許可するか、外部URLも許可するかを決め、その条件に合わない値を保存しない処理を考えます。空欄ならbutton自体を表示しないのか、既定の移動先を使うのかも、値の仕様に含めます。
色も同じです。色を一つ選べるようにしたいのか、任意のCSSの指定を受けたいのかで、許可する値は変わります。表示件数なら、文字として入力された値を、そのまま件数として扱うわけにはいきません。最低何件、最大何件にするかをtheme側で決めます。layoutをselectで選ばせる場合は、表示した選択肢の一つだけを保存するのか、将来追加する値をどう扱うのかを決めます。
この区別をしないと、管理画面には便利そうな項目だけが増えます。変更できる人は迷い、themeを直す人は、どの値がどこへ影響するか探すことになります。必要なのは設定できる項目の数ではありません。日常的に変える内容と、間違って変えると困る内容を分けることです。
controlの名前とsettingの役割を混同しない
Customizerでは、settingが保存する値を表し、controlが操作画面を表します。一つの見た目を作るためにsettingとcontrolを続けて書くため、二つを同じもののように扱いやすくなります。しかし、controlを替えても、保存する値の意味が変わるとは限りません。controlは入力する人に何を選ばせるかを決め、settingはその結果をどの形で残すかを決めます。
$wp_customize->add_setting( 'header_link_url', array(
'default' => '',
'sanitize_callback' => 'esc_url_raw',
) );
$wp_customize->add_control( 'header_link_url', array(
'label' => 'header buttonのURL',
'section' => 'title_tagline',
'type' => 'url',
) );
この例では、header_link_urlが保存するsettingで、typeがurlのcontrolは入力画面です。実際に採用するcallbackは、URLの使い方と保存先に合わせます。codeを別のthemeからコピーするだけで決めず、設定値がどこで使われるかを確認します。
ここで、保存前に扱うことと、出力時に扱うことも分けます。sanitize_callbackは、設定値を保存するときの入口です。保存したURLをlinkへ出すとき、保存した見出しをHTMLへ出すとき、保存した色をstyleへ出すときには、それぞれ表示する場所に合った扱いを考えます。保存前の処理を一つ書いたから、どの場所でもそのまま表示してよいという意味にはなりません。値がどこを通るかを、一方向にたどります。
たとえば、見出し文を設定した場合は、入力欄、setting、保存値、template内の表示箇所の順に確認します。途中でHTMLとして扱うのか、単なる文字として扱うのかが変われば、判断も変わります。URLなら、入力欄、保存、hrefとして使う箇所までを確認します。設定名だけを見てcallbackを選ぶのではなく、最終的な用途を見て決めます。
previewで見えることと保存できることは別である
Customizerのpreviewは、設定を替えたときの見た目をすぐ確かめるために役立ちます。ただし、previewで文字や色が変わったことだけでは、保存後の値が正しいとは決まりません。画面内のJavaScriptが一時的に表示を変えているだけかもしれません。設定を保存し、Customizerを閉じ、公開側のpageを開き直して確認します。
確認には、正しい値だけを使いません。URLなら空欄と通常のURL、表示件数なら最小値と最大値の外側、selectなら用意していない値を考えます。すべてを画面から入力できるとは限らなくても、保存値が想定外になった場合に、templateがどう表示するかは決めておく必要があります。値を消したときに壊れたlinkが残る、選択肢にないlayoutでHTMLが途中までしか出ない、といった状態を残さないためです。
settingを追加したら保存後の画面まで確認する
設定項目を追加する前に、設定名、入力する人、変更できる範囲、表示する場所を一枚のメモにします。その後でsettingとcontrolを書けば、callbackを何のために置くのかが曖昧になりません。実装の作業順は次のようにします。
- 設定値を使う場所と、許可する値の形を一つ決める。
- 空欄、既定値、想定外の値をどう扱うかを決める。
- settingへdefaultと
sanitize_callbackを指定する。 - controlの入力形式をsettingの目的へ合わせる。
- 正しい値、空欄、想定外の値を入れて保存する。
- 保存後のsite表示と、設定画面を開き直したときの値を確認する。
- 値を使うtemplateを開き、変更が必要な範囲だけに及んでいるかを見る。
この順序なら、最初から複雑な設定画面を作る必要はありません。まずheaderのURLのように用途が一つで、保存値の形が決めやすい項目から始めます。項目を増やすのは、運用する人が実際に同じ変更を繰り返すと分かってからで構いません。themeのcodeを編集する方が安全な変更まで、Customizerへ移す必要はありません。
設定項目を外部の制作者が追加する場合も、誰が入力し、何を変更でき、値をどこで使うかを渡します。設定画面を作る作業と、公開siteのURL、見出し、layoutを決める責任は分けます。引継ぎでは、設定名と画面の説明だけでは足りません。空欄にしてよいか、変更後にどのpageを確認するか、戻す場合はどの既定値へ戻すかも共有します。
sanitize_callbackは、Customizerを安全そうに見せるための飾りではありません。設定項目が受け取る値を具体的に決める場所です。入力欄を増やす前に、保存する値、表示する場所、変更する人を対応させます。その対応が決まっていない項目は、まだCustomiserへ追加しません。
関連記事

