- 結論
- 原因・仕組み
- 手順(サンプルコード)
- 動作確認(検証環境と結果)
- wp_localize_script と wp_add_inline_script の違いの注意点
- wp_localize_script と wp_add_inline_script の違いでよくあるミス
- wp_localize_script と wp_add_inline_script の違いのチェックリスト
- wp_localize_script と wp_add_inline_script の違いのFAQ(よくある質問)
- 筆者の見解(wp_localize_script と wp_add_inline_script の違い)
- wp_localize_script と wp_add_inline_script の違いの関連項目
- 出典(一次情報)
結論
PHP の値を JavaScript に渡す手段は主に2つあります。
wp_localize_script(): 翻訳文字列(ローカライズ)を渡す本来の用途向け。第3引数の配列をvar 名前 = {...}の形で出力する。スカラー値が文字列になる。wp_add_inline_script(): 任意の JS コードを、スクリプトの前(before)か後(after)に追加する。WordPress 4.5.0 で追加。型を保った JSON を渡せる。
公式リファレンスにも、wp_localize_script() は「実際に文字列をローカライズするとき」に使い、一般的なデータの受け渡しには wp_add_inline_script() を使うよう書かれています。新規実装なら、翻訳以外は wp_add_inline_script() に wp_json_encode() を組み合わせるのが無難です。
原因・仕組み
wp_localize_script() が内部で作る JS では、トップレベルのスカラー値は文字列になります。リファレンスにも、真は "1"、偽は空文字になる旨の記載があります。そのため、true を渡したつもりが JS 側で "1" になり、if ( cfg.debug === true ) が成立しない、という不具合が起こります。
出力位置も異なります。localize のデータは、対象スクリプトの直前に <script id="ハンドル-js-extra"> として出力されます。wp_add_inline_script() は、before を指定すると直前、after(既定)なら直後です。どちらも、対象のハンドルが登録(またはキューに追加)済みである必要があります。
手順(サンプルコード)
同じ設定値を、2つの方法で渡して比較する例です。
add_action( 'wp_enqueue_scripts', function () {
wp_register_script( 'ks-main', get_theme_file_uri( 'js/main.js' ), array(), '1.0', true );
wp_enqueue_script( 'ks-main' );
$cfg = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'perPage' => 10,
'debug' => true,
'labels' => array( 'ok' => '完了', 'max' => 3 ),
);
// 方法1: localize(翻訳文字列向け。数値・真偽が文字列になる)
wp_localize_script( 'ks-main', 'ksLocalized', $cfg );
// 方法2: inline(型を保つ。before で main.js より先に定義)
wp_add_inline_script( 'ks-main', 'window.ksInline = ' . wp_json_encode( $cfg ) . ';', 'before' );
} );
翻訳文字列だけを渡すなら、localize も適切です。その場合は __() で翻訳した文字列を配列に入れます。
動作確認(検証環境と結果)
WordPress 7.1.2、PHP 8.2.12 で、フッターのスクリプト出力を取得しました(php C:Tempwp-testrun.php localize-script-vs-add-inline-script.php)。
localizeの出力:var ksLocalized = {"ajaxUrl":"http://localhost/wp-admin/admin-ajax.php","perPage":"10","debug":"1","ratio":"1.5","labels":{"ok":"完了","max":3}};。トップレベルのperPageは"10"、debugは"1"、ratioは"1.5"と文字列になった。入れ子のlabels.maxは数値 3 のままだった。inline(before)の出力:window.ksInline = {"ajaxUrl":"http://localhost/...","perPage":10,"debug":true,"ratio":1.5,...}。型が保たれた。- 出力順は、
ks-main-js-extra(localize)、ks-main-js-before、本体のks-main-js、ks-main-js-afterの順になった。 - 未登録のハンドル
ks-nothingへのwp_add_inline_script()とwp_localize_script()は、どちらもfalseを返し、何も出力されなかった。
ブラウザ上で JS の値の型を typeof で確認する検証は、行っていません。
wp_localize_script と wp_add_inline_script の違いの注意点
wp_add_inline_script()に<script>タグを含めてはいけません(含めるとタグが取り除かれる旨が公式に記載されています)。- JSON を渡すときは
json_encode()ではなくwp_json_encode()を使います(wp_json_encode() の使い方|説明・引数・注意点)。 - 渡す値に、ユーザー入力が含まれる場合、
wp_json_encodeは JS 文字列としては安全に出力しますが、JS 側でinnerHTMLに入れる処理でXSSにならないように注意します。 - nonce は、キャッシュされるページに埋め込むと期限切れになります(wp_create_nonce() の使い方|説明・引数・注意点)。
- 大きなデータをインラインで出すと、HTML が肥大化します。大量なら REST API で別取得にします。
wp_localize_script と wp_add_inline_script の違いでよくあるミス
wp_localize_script()を、対象ハンドルの登録(wp_register_script()またはwp_enqueue_script())より前に呼び、何も出力されない(本検証でも未登録ハンドルへの呼び出しはfalse)。trueを渡して JS 側で=== trueと比較する。文字列の"1"になる。wp_add_inline_script()を、wp_headの中の独立した場所で呼び、対象ハンドルが未登録のまま。- 変数名にハイフンを含める。JS の変数名として不正になります。
module型のスクリプトにインラインでグローバル変数を渡し、スコープが合わない。
wp_localize_script と wp_add_inline_script の違いのチェックリスト
- 翻訳文字列か、設定値かを判断したか。
- 設定値なら
wp_add_inline_scriptとwp_json_encodeを使ったか。 - 対象ハンドルは、呼び出し時点で登録済みか。
- JS 側の型比較を、実際の出力に合わせたか。
- ユーザー入力を含む値は、描画時にエスケープしているか。
wp_localize_script と wp_add_inline_script の違いのFAQ(よくある質問)
Q. wp_localize_script は非推奨ですか。
A. 公式リファレンスの時点では非推奨とはされていません。翻訳文字列以外の用途では、wp_add_inline_script が推奨されています。
Q. before と after はどう使い分けますか。
A. 本体が読み込まれる時点で変数が必要なら before、本体の関数を呼ぶ処理なら after を使います。
Q. 複数回呼べますか。
A. wp_add_inline_script は同じハンドルへ複数回追加でき、本検証でも before と after を併用できました。
筆者の見解(wp_localize_script と wp_add_inline_script の違い)
私見では、新しく書くコードで wp_localize_script を設定値の受け渡しに使う理由は、あまりありません。型が変わる挙動は、気づきにくい不具合の元だからです。ただし、既存のテーマやプラグインは localize を使っていることが多く、すぐ全部を書き換える必要まではないとも考えます。触るついでに、少しずつ置き換えるのが現実的です。
wp_localize_script と wp_add_inline_script の違いの関連項目
- wp_localize_script() の使い方|説明・引数・注意点
- wp_add_inline_script() の使い方|説明・引数・注意点
- wp_json_encode() の使い方|説明・引数・注意点
- wp_enqueue_script が読み込まれない原因
- wp_enqueue_script で defer / async を付ける方法(準備中)
