0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WordPress 7.0のiframeエディタで、クラシックメタボックスが引き起こす問題と移行【register_post_meta】

0
Last updated at Posted at 2026-07-19

2026年8月に追記しました。7.1 が8月19日にリリースされ、iframe 化に付いていた条件がなくなったので、その点を書き直しています。あわせて「データ API に寄せきれないコードをどうするか」を1節足しました。元記事はデータ API へ移す話だけで止まっていて、移せない場合の答えがなかったためです。

【日付を入れる】、自分のプラグインを 7.0 で動かしたら、メタボックスに仕込んでいた JavaScript が急に効かなくなりました。

エラーも出ていません。ただ、いつも掴んでいたはずのエディタの要素が document.querySelector で取れない。null が返ってくる。半年前に書いて、ずっと動いていたコードです。何も変えていないのに、動かなくなった。

先に結果を書くと、原因はエディタが iframe の中に入ったことでした。そしてこの件を追いかけているうちに、add_meta_box で作ってきたメタボックスそのものが、7.0 の新しい編集体験と噛み合わなくなっていることも分かりました。この2つは根が同じで、直し方も同じです。

検証環境:【WordPress のバージョンと確認日を入れる】。最終的な挙動は、公式のフィールドガイドと自分の環境で確認してください。

掴めなくなった理由

7.0 の前まで、ブロックエディタは管理画面と同じページの中で動いていました。だからメタボックスに置いた JavaScript から、エディタの要素を document.querySelector で掴んで、値を読んだり書いたりできた。同じ文書の中にあったからです。

7.0 では、エディタが iframe の中に入ります。iframe は外側のページとは別の文書です。外から document.querySelector でエディタ内の要素を探しても、見つかりません。

// ❌ iframe化で動かなくなる:外側のdocumentからエディタ内を探す
const title = document.querySelector('.editor-post-title__input');
title.value = '...'; // iframe内なので、外側のdocumentからは掴めない

**7.0 の時点では、これは条件付きでした。**投稿に挿入されているブロックの API バージョンが全部 3 以上なら iframe 化し、1つでも古いものがあれば iframe を外して互換性を保つ、という判定が入っていたからです。だから環境によっては、まだ壊れていませんでした。

7.1 で、その判定がなくなりました。テーマがブロックテーマかクラシックテーマかにも、ブロックの API バージョンにも関係なく、常に iframe 化されます。**レガシーなメタボックスを登録しているサイトも例外ではありません。**7.0 のときに「うちはまだ iframe にならないから」で先送りしていた場合、8月19日からその逃げ道はなくなりました。

余談ですが、Gutenberg プラグインの 22.6 以降はプラグインが有効なら強制的に iframe 化されます。手元で先に再現したいなら、これが早いです。

クラシックメタボックスの、もう一つの問題

JS が掴めない件を追ううちに、add_meta_box 自体にも別の問題があると分かりました。

7.0 の目玉は、複数人が同じ投稿を同時に編集する仕組みです。ここに制約があります。クラシックメタボックスがある投稿タイプは、その同時編集が無効になる。Classic ブロック(core/freeform)がある投稿も同様です。

つまり add_meta_box を使い続けると、その投稿タイプだけ新しい編集体験から外れます。動かなくなるわけではありませんが、新機能に乗れない旧道に取り残される。しかも iframe 化で、メタボックス内の JS も見直しが要る。旧来のやり方が、二重に効かなくなっていく感じでした。

移行:register_post_meta に寄せる

対処は、メタボックスでやっていたことを、登録済みメタと REST 公開に移すことです。iframe の件も、メタボックスの件も、これで一度に片づきます。

まず、自分のプラグインの add_meta_box を全部洗い出します。ここが移行の起点です。

grep -rn "add_meta_box" ./

見つかったメタを register_post_meta で登録し直します。肝は show_in_rest => true です。これがあると、ブロックエディタ側から REST 経由でメタを読み書きできるようになります。

add_action('init', function () {
    register_post_meta('post', 'myplugin_subtitle', [
        'show_in_rest'  => true,   // これでエディタ(REST)から扱える
        'single'        => true,
        'type'          => 'string',
        'auth_callback' => function () {
            return current_user_can('edit_posts');
        },
    ]);
});

auth_callback を省くと権限チェックが緩くなります。誰がこのメタを書き換えられるかを、ここで明示しておきます。

入力UIは、エディタ側のパネルで出す

メタボックスの HTML フォームの代わりは、エディタのサイドパネルに置きます。ここは JavaScript 側の実装になります。

DOM を直接掴んでいたころと違い、useEntityProp でメタを読み書きします。**iframe の内か外かを気にしなくて済むのが、この形の利点です。**エディタが管理しているデータに、正規の経路で触るからです。冒頭で null が返ってきた原因は、そもそも DOM を掴みにいっていたことでした。

コードは末尾にまとめて置きます。

データAPIに寄せきれないコードをどうするか

ここが今回の追記です。元記事はデータ API に移す話で終わっていましたが、実際には移しきれないコードが残ります。

サードパーティのライブラリを噛ませている、既存の jQuery プラグインをそのまま動かしている、キャンバス内の要素の座標を測っている。こういうものは、useEntityProp では置き換えられません。

その場合の定石が2つ示されています。

ひとつは、**グローバルな document や window を掴むのをやめて、キャンバス内の要素から辿ること。**要素の ownerDocument が、その要素が属する文書です。そこから defaultView を取れば、対応する window が得られます。

// ❌ どの文書か分からないまま掴む
const doc = document;

// ✅ キャンバス内の要素から、その要素が属する文書を辿る
const doc  = node.ownerDocument;
const view = doc.defaultView;

もうひとつは、**イベントリスナの登録と解除に useRefEffect を使うこと。**iframe は再マウントされることがあるので、登録しっぱなしにすると、消えた文書にリスナが残ります。ref に紐づけておけば、要素が外れたときに解除まで走ります。

不具合の原因は、ほぼこの1点に集約されると書かれています。**iframe が独自の document と window を持っていて、エディタスクリプトが動く管理画面とは別だから。**グローバルを掴んでいるコードは、全部違う文書を見に行きます。

自分の場合、移行できたものはデータ API に寄せて、どうしても DOM を触る必要が残った箇所だけ ownerDocument 経由に書き換えました。全部をデータ API に寄せる必要はありません。

保存側は、そのままでいい部分もある

register_post_meta で show_in_rest を有効にしておくと、エディタからの保存は REST 経由で処理されます。旧来の save_post で $_POST を拾って update_post_meta していた処理は、エディタ経由の保存では通らなくなることがあります。

ただ、クラシックエディタや外部からの保存経路も残すなら、save_post 側を併存させる判断はありえます。自分は、エディタ経由を REST に寄せつつ、nonce と権限を見たうえで save_post も残す形にしました。ここは、プラグインがどの経路から保存されうるかで変わります。

確認する順番

移行したら、この順で確かめます。

確認すること 見る場所 外れていたときの原因
メタが REST に出ているか /wp-json/wp/v2/posts/{id} の meta show_in_rest が無い
パネルで読み書きできるか エディタのサイドパネル auth_callback か登録先の post type
旧JSが残っていないか grep -rn "document.querySelector" ./ iframe 前提の DOM 操作
残す DOM 操作が文書を辿っているか ownerDocument を使っているか グローバルな document を掴んでいる

3行目が、冒頭の自分のミスそのものです。4行目は今回足しました。document.querySelector を消しただけでは足りず、残した DOM 操作が正しい文書を見ているかまで確認が要ります。

コード

エディタのドキュメント設定パネルに、メタの入力欄を足す形です。

import { registerPlugin } from '@wordpress/plugins';
import { PluginDocumentSettingPanel } from '@wordpress/editor';
import { useEntityProp } from '@wordpress/core-data';
import { TextControl } from '@wordpress/components';

const Panel = () => {
    const [meta, setMeta] = useEntityProp('postType', 'post', 'meta');
    return (
        <PluginDocumentSettingPanel title="Myplugin">
            <TextControl
                label="サブタイトル"
                value={ meta.myplugin_subtitle || '' }
                onChange={ (v) => setMeta({ ...meta, myplugin_subtitle: v }) }
            />
        </PluginDocumentSettingPanel>
    );
};
registerPlugin('myplugin-panel', { render: Panel });

PluginDocumentSettingPanel の import 元は @wordpress/editor です。古い記事では @wordpress/edit-post から取っているものがあります。

まとめ

  • 7.0 でエディタが iframe 化。7.1 で条件がなくなり、テーマ種別にもブロック API バージョンにも関係なく常に iframe
  • 外側の document からエディタ内 DOM は掴めない
  • クラシックメタボックス(add_meta_box)がある投稿タイプは、同時編集が無効になる
  • 対処は register_post_meta + show_in_rest => true。iframe 対応とメタボックス問題を一度に解決
  • 入力 UI はエディタのパネルへ。useEntityProp でメタを読み書きする
  • データ API に寄せきれない DOM 操作は、ownerDocument と defaultView を辿る。リスナは useRefEffect
  • 保存経路は要確認。エディタ経由は REST。save_post を残すかはプラグイン次第
  • 手元で先に再現したいなら、Gutenberg プラグイン 22.6 以降を入れる

7.0 対応で、いちばん腰が重かったのがこの移行でした。長く使ってきた書き方なので。ただ、データを REST に出す形に寄せておくと、iframe 化にも同時編集にも乗れて、結果として身軽になりました。

そして 7.1 からは、腰が重いかどうかに関係なく、iframe は必ず来ます。


ふだんはraplsworks.comで、WordPressプラグイン開発やClaude Codeまわりのことを書いています。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?