WordPressのwp_slash()とは? コメント編集でバックスラッシュが消えた原因を理解する

wp_slash()とwp_unslash()の往復でバックスラッシュを保持する流れ

WordPressでコメント編集機能を作ったとき、新規投稿では残っていたWindowsパスのバックスラッシュが、編集して保存すると消える問題が起きました。

画面では正しく入力できています。それでも保存後は文字列が変わり、パスとして使えませんでした。原因を追うと、独自の更新処理とWordPress本体の両方で、入力値からスラッシュを外していたことが分かりました。

この記事では、その修正で使った wp_slash() を中心に、wp_unslash()、wp_update_comment()との関係を整理します。

新規コメントでは残り、編集すると消えた

対象にしていたのは、コメントへ共有ファイルのパスを貼り、表示側でコピーしやすくする機能です。たとえば、次のようなダミーのパスを扱います。

Z:\example\docs\manual.pdf

新しいコメントとして投稿したときは、バックスラッシュが残りました。しかし、同じコメントを編集して更新すると、保存後の文字列からバックスラッシュが消えました。

つまり、表示用のコピー処理ではなく、編集内容を保存する経路に問題があると絞り込めます。新規投稿と編集で使う処理を比較し、更新側を確認しました。

wp_slash()とwp_unslash()の役割

wp_slash()は、文字列または配列の値へスラッシュを追加するWordPress関数です。配列を渡した場合は、その中の値も再帰的に処理します。

wp_unslash()は反対に、文字列または配列の値からスラッシュを取り除きます。フォーム入力を扱うコードで見かけることが多い関数です。

ここでいうスラッシュ処理は、URLの区切り文字を整える話ではありません。WordPressが入力値やデータベースへ渡す値を扱うときの、文字列の状態に関する処理です。

wp_update_comment()は内部でwp_unslash()する

コメントを更新していたのは、WordPress標準の wp_update_comment() です。公式の関数リファレンスでソースを確認すると、渡された配列に対して内部で wp_unslash() が実行されます。

$data = wp_unslash( $commentarr );

独自の更新処理では、それより前にも受け取った値へ wp_unslash() を使っていました。その状態のまま wp_update_comment() へ渡すと、同じ方向の処理がもう一度かかります。

フォーム入力 → 独自処理でunslash → wp_update_comment()内でもunslash → バックスラッシュが失われる

バックスラッシュが消えたのは、保存後の表示だけの問題ではありませんでした。更新APIへ渡す直前のデータ状態と、API内部で行われる処理が合っていなかったことが原因です。

最小例で往復を確認する

まずデータベースを更新せず、wp_slash() と wp_unslash() の往復だけを確認できます。次のコードはWordPressが読み込まれたローカル検証環境で実行する最小例です。本番サイトではなく、削除できる一時的なプラグインや検証コードから実行します。

$original = 'Z:\\example\\docs\\manual.pdf';

$prepared = wp_slash([
    'comment_content' => $original,
]);

$inside_core = wp_unslash($prepared);

var_dump($inside_core['comment_content'] === $original);
// bool(true)

PHPの単一引用符で実際のバックスラッシュ1文字を表すため、コード上では \\ と書いています。wp_slash() でAPIへ渡す状態を作り、内部処理に見立てた wp_unslash() の後に元の文字列へ戻ることを確認しています。

更新直前にwp_slash()を使う

実際の修正では、内容を検証・整形した後、wp_update_comment() へ渡す配列全体を wp_slash() で処理しました。要点を抜き出すと次の形です。

$content = wp_kses_post($content);

$result = wp_update_comment(
    wp_slash([
        'comment_ID'      => $comment_id,
        'comment_content' => $content,
    ]),
    true
);

この断片は、更新処理の境界だけを示しています。実際のフォーム処理では、この前にnonceの検証、操作権限の確認、コメントIDの検証が必要です。$comment_id や $content へ、未検証のリクエスト値をそのまま入れるコードではありません。

wp_kses_post() で許可するHTMLへ整えた後、WordPressの更新APIへ渡す直前に wp_slash() を使います。配列全体を渡すことで、comment_content だけを個別に処理する必要もありません。

wp_update_comment() の第2引数を true にすると、失敗時に WP_Error を受け取れるため、成功・失敗を分けて確認できます。

修正後に確認したこと

修正後は、使い捨てられる検証用コメントで次の順番を確認しました。

  1. バックスラッシュを含むダミーのWindowsパスを入力する
  2. コメントを保存し、画面を再読み込みする
  3. 同じコメントを編集して、もう一度更新する
  4. 表示されたパスとコピーした文字列が入力値と一致するか比べる

新規投稿だけでなく、編集後もバックスラッシュが残り、パスとしてコピーできることまで確認しました。これで、表示処理と更新処理の両方がつながっていると判断できます。

使う場所を増やしすぎない

wp_slash() をすべての入力へ付ければよいわけではありません。今回必要だったのは、内部で wp_unslash() するWordPress APIへ、すでに整えた値を渡す境界でした。

  • まず、値が失われるのが入力・保存・表示のどこかを切り分ける
  • 呼び出すWordPress関数の公式リファレンスとソースを確認する
  • addslashes() や stripslashes() を推測で重ねない
  • 修正は更新APIへ渡す直前の狭い範囲に置く
  • 保存後の文字列まで比較する

すでにバックスラッシュが失われたコメントは、元の位置をコードから判断できません。その場合は元のパスを確認し、正しい文字列を貼り直す必要があります。

WordPressの内部処理まで見て原因をつなぐ

今回の問題は、「編集すると記号が消える」という小さな表示差から始まりました。新規と編集の違いを比べ、更新関数の内部処理を確認すると、二重のunslashという原因までつながりました。

入力値を整える処理と、WordPress APIが内部で行う処理を一つの流れとして見る。

独自の投稿・コメント機能を作るときは、保存関数の名前だけでなく、受け取るデータの状態も確認する必要があります。コメント機能を含むサイト設計の流れは、社内ポータルの投稿・コメント機能を設計した記録でもまとめています。