本記事にはアフィリエイトリンクを含みます。Amazonのアソシエイトとして収益を得る場合があります。

WordPressプラグイン開発記 vol.3 – スラッグ変更時に重複チェックを行う

WordPressのアイキャッチ WordPress
WordPress

前回の記事でWordPressに作成したプラグインを認識させることができました。いよいよ、実際に機能を実装していきたいと思います🫡

ブロックエディターはReactベースなので、Reactをほぼ触ったことがない筆者には難易度高めな気がしてなりませんが、まずは小さな機能から始めてみようと思います。

この記事でわかること

  • WordPressのブロックエディターでスラッグの重複チェックを行う方法。
  • PHP(REST API)とJavaScript(MutationObserver・wp.data・wp.apiFetch)を組み合わせた実装手順。
  • プラグインの共通クラス構成(Config・管理クラス)の作り方。

スラッグの重複チェックを行いたい

スラッグって変更した時点では重複しているかどうかわかりませんよね。全記事のスラッグ覚えろってかー、です。で、既に存在しているスラッグのまま記事を保存するとWordPressが *****-2 みたいにしれっと連番をつけて保存してくれます。警告やメッセージもなく、いつの間にか変更されてたスラッグが保存されます。確かに重複しないのですが、意図しないURLになってしまうのは非常に残念です……。

というわけで記事編集画面でスラッグを変更したときに重複チェックを行う機能を追加してみようと思います。

投稿編集画面の右側にある設定エリアでスラッグを変更できますが、ここが変わったタイミングで重複を検知できれば、そのまま保存してスラッグが変わってしまうことは防げそうです。

スラッグを変更するためのボタン。

ただしこのエリアのボタンは button タグなのでchangeイベントを検知することができません。そのため今回はスラッグを入力するポップアップのクローズボタンクリック時に確認する方針にしてみます。

スラッグ変更のポップアップの閉じるボタン

ファイル・ディレクトリ構成

今回の機能追加後のプラグインディレクトリ内の構成は下記の通りです。

実装内容(共通部)

今回が初めての機能実装になるので、個別機能の実装の前に共通的なクラスを整えておきます。

プラグイン本体

追加していく機能を読み込んだりするクラスをロードするようにしています、のでプラグインヘッダー以外は今後あまり変更することはない!?と思います。

chun-log-customize.php

プラグインの構成情報を管理するクラス

プラグイン全体でよく使う情報(バージョン・ディレクトリパス・URL)をまとめたクラスです。各機能クラスからここを参照する形にしています。

ChunLogCustomize_Config.php

サーバー側のクラスを一括管理するクラス

各機能クラスのインスタンスをここで生成・保持して「どのクラスを初期化するか」を1ファイルに集約しています。また、誤って複数回インスタンスを生成してしまうのを防ぐためにシングルトンパターンで実装しています。

ChunLogCustomize.php

実装内容(スラッグ重複チェック機能)

スラッグ重複チェックを行うクラス

重複チェックのREST APIエンドポイント登録・権限チェック・JS/CSSの読み込みをこのクラスにまとめています。このクラスをロードするとスラッグ重複チェックの一式が準備されるようなイメージですね。

ChunLogCustomize_SlugChecker.php

WP_Queryで発行されるSQLは下記の通りです。post_type => 'any'と指定したのにSQLではIN ('post', 'page', 'attachment')になっていますが、これはWordPressが内部的に登録されている投稿タイプを展開した結果です。カスタム投稿タイプを追加している場合はそれも含まれるので意図通りの動作です。

発行されたSQL

スタイルシート

エラー発生時にスラッグ設定行の背景を赤くするスタイルです。WordPressのエラー通知と同じ背景色を設定しています。

slug-check.css

エディター画面のJavaScript

3つのポイントを補足します。

  • MutationObserverでポップアップの出現を監視する
    スラッグ編集ポップアップはブロックエディターが動的に生成するため、ページロード時点ではDOMに存在しません。document.bodyを監視してポップアップが出現したタイミングでクローズボタンにイベントを登録しています。
  • dataset.boundで二重登録を防止する
    MutationObserverは細かいDOM変化でも発火するため、同じボタンに何度もイベントリスナーが登録されないようフラグを立てています。
  • スラッグの取得にはwp.dataを使う
    DOMから直接値を取得するのではなくselect('core/editor').getEditedPostAttribute('slug')でエディターのストアから取得することで、WordPressが処理した後の正規化済みスラッグを確認できます。
slug-check.js

動作確認

実装が完了したので動作を確認してみます。既存の記事と同じスラッグを入力してポップアップを閉じると……画面上部にエラー通知が表示され、スラッグの入力行が赤くハイライトされました🎉

スラッグ重複エラーの状態

重複していないスラッグに変更するとエラーが消えることも確認できました。

Q&A

Q
ゴミ箱に入れた投稿のスラッグは重複扱いになる?
A

なりません。post_statustrashを含めていないため、ゴミ箱の投稿はチェック対象から除外されます。一度ゴミ箱に移した後で同じスラッグを再利用したい場合も問題なく使えます。

Q
カスタム投稿タイプも重複チェックの対象になりますか?
A

なります。post_type => 'any'を指定しているためWordPressに登録されている全投稿タイプが対象になります。発行されるSQLでIN ('post', 'page', 'attachment', ...)のように展開されるので、カスタム投稿タイプのスラッグとの重複も検知できます。

Q
REST APIにnonce検証は必要ですか?
A

必須です。wp.apiFetchが自動でX-WP-Nonceヘッダーを付与してくれますが、サーバー側でもwp_verify_nonce()を使って必ずチェックするようにしましょう。認証なしでエンドポイントを公開するのはセキュリティ上のリスクになります。

おわりに

ブロックエディターのDOM構造はReactで動的に生成されるためReactをほぼ知らない筆者にはとっつきにくい部分もありましたがwp.dataMutationObserverを使うことでなんとか動くものができました。

PHPは5の時代に触っていましたが今回PHP 8を使ってみると??=演算子や型宣言まわりでだいぶ変わったなぁという感じでした。次回はまた別の機能を追加していきます。


WordPressプラグイン開発記

当ブログの内容はできる限り正確な情報を提供するよう努めていますが、利用にあたっては自己責任でお願いいたします。
掲載内容に基づく操作・設定などによって生じたトラブルや損害について、当サイトは一切の責任を負いません。
タイトルとURLをコピーしました