WordPress エスケープ処理
      WordPress でデータを無害化 (サニタイズ) する方法について。
更新日:2025年04月06日
作成日:2019年01月17日
エスケープ処理
WordPress のテーマで文字列を echo や print などを使って出力する際は、それらを適切にエスケープ処理する必要があります。PHP には、htmlspecialchars() 関数などのエスケープ処理用の関数がありますが、WordPress にも文字列を適切にエスケープしたり、HTML タグや URL を処理してくれる関数が用意されています。
変数や関数などの値や文字列を出力する場合は、用途によってエスケープやサニタイズの方法を適切に選択してセキュリティ上のリスクを回避する必要があります。
参考サイト:日本語 Codex「データ検証」
the_xxxx と get_xxxx
テンプレートタグには、the_title() のように値を出力(echo)するものと、get_the_title() のように出力はせず値を返すだけのものがあります。
the_ を前置するテンプレートタグは、WordPress が echo を行っているテンプレートタグで(適切にエスケープされて出力されるので)安全に使用することができます。そのため、何らかの出力を行う際は(可能であれば) the_xxxx 関数を使用するようにします。
<a href="<?php the_permalink(); ?>">
get_ を前置するテンプレートタグは値を返すテンプレートタグなので、出力する場合は適切にエスケープ処理を行う必要があります。
例えば、前述のサンプル the_permalink() の定義(ソース)を確認すると以下のようになっています。
function the_permalink( $post = 0 ) {
  echo esc_url( apply_filters( 'the_permalink', get_permalink( $post ), $post ) );
}
          get_permalink() で取得した値に「the_permalink」フィルターフックを適用して、esc_url() でエスケープ処理後に出力されています。
以下は、the_title() と get_permalink() を使ってタイトルにリンクを付けて h2 要素で出力する例です。
the_title() は第一引数と第二引数にタイトルの前後に配置するテキスト(文字列)を指定することができます。この場合、引数に文字列として指定するので the_permalink() は使えず get_permalink() を使いますがエスケープ処理が必要になります。
<?php the_title( '<h2><a href="' . esc_url( get_permalink() ) . '">', '</a></h2>' ); ?>
esc_html
esc_html() は HTML で特別な意味を持つ文字(&、<、>、"、')をエスケープ(エンコード)して & や < のような文字参照(HTMLエンティティ)と呼ばれる表記に変換します。そして esc_html フィルターを通して出力します。
esc_html( $text )
- パラメータ
 - $text(string):(必須) エスケープするテキスト
 
- 戻り値
 - エスケープされた HTML 文字列
 
<?php $html = esc_html( '<a href="http://www.example.com/">A link</a>' ); echo $html; ?> //出力 <a href="http://www.example.com/">A link</a>
上記のようにすると「A link」ではなく、文字列として「'<a href="http://www.example.com/">A link</a>'」と出力されます。
また、この関数は既にエンコードされている場合は二重にエンコードしません(例えば、文字列中に「<」が含まれている場合、この中の「&」をさらに「&」に置換は行いません)。
以下の場合、「 A & B」と出力され、「A &amp; B」とは出力されません。
echo esc_html( 'A & B' );
esc_html() は全てのタグをエスケープしてしまいますが、特定のタグはそのまま出力させたい(特定のタグ以外を除去する)場合は、wp_kses() を使用します。
既にエンコードされている文字を二重にエンコードする必要がある場合は、esc_textarea() を使用します。
以下は esc_html() のソースです。
wp_check_invalid_utf8() で無効な UTF-8 の文字をチェック後、_wp_specialchars() でエスケープ処理し、esc_html フィルターフックを適用して返しています。
function esc_html( $text ) {
    $safe_text = wp_check_invalid_utf8( $text );
    $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES );
    /**
     * Filters a string cleaned and escaped for output in HTML.
     * Text passed to esc_html() is stripped of invalid or special characters
     * before output.
     * @since 2.8.0
     * @param string $safe_text The text after it has been escaped.
     * @param string $text      The text prior to being escaped.
     */
    return apply_filters( 'esc_html', $safe_text, $text );
}
            以下はシステム関数 _wp_specialchars() のソースです。
対象となる文字列(&<>"\')が含まれていれば、文字コードなどを調べたりして PHP の htmlspecialchars() を適用しています。
esc_html() の場合、_wp_specialchars() を適用する際は $double_encode(既にエスケープされている文字を更にエスケープするかどうか)パラメータを指定せずに htmlspecialchars() を呼び出して2重にエンコードされないようにしています。
function _wp_specialchars( $string, $quote_style = ENT_NOQUOTES, $charset = false, $double_encode = false ) {
    $string = (string) $string;
    if ( 0 === strlen( $string ) ) {
        return '';
    }
    // Don't bother if there are no specialchars - saves some processing
    if ( ! preg_match( '/[&<>"\']/', $string ) ) {
        return $string;
    }
    // Account for the previous behaviour of the function when the $quote_style is not an accepted value
    if ( empty( $quote_style ) ) {
        $quote_style = ENT_NOQUOTES;
    } elseif ( ! in_array( $quote_style, array( 0, 2, 3, 'single', 'double' ), true ) ) {
        $quote_style = ENT_QUOTES;
    }
    // Store the site charset as a static to avoid multiple calls to wp_load_alloptions()
    if ( ! $charset ) {
        static $_charset = null;
        if ( ! isset( $_charset ) ) {
            $alloptions = wp_load_alloptions();
            $_charset   = isset( $alloptions['blog_charset'] ) ? $alloptions['blog_charset'] : '';
        }
        $charset = $_charset;
    }
    if ( in_array( $charset, array( 'utf8', 'utf-8', 'UTF8' ) ) ) {
        $charset = 'UTF-8';
    }
    $_quote_style = $quote_style;
    if ( $quote_style === 'double' ) {
        $quote_style  = ENT_COMPAT;
        $_quote_style = ENT_COMPAT;
    } elseif ( $quote_style === 'single' ) {
        $quote_style = ENT_NOQUOTES;
    }
    if ( ! $double_encode ) {
        // Guarantee every &entity; is valid, convert &garbage; into &garbage;
        // This is required for PHP < 5.4.0 because ENT_HTML401 flag is unavailable.
        $string = wp_kses_normalize_entities( $string );
    }
    $string = @htmlspecialchars( $string, $quote_style, $charset, $double_encode );
    // Back-compat.
    if ( 'single' === $_quote_style ) {
        $string = str_replace( "'", ''', $string );
    }
    return $string;
}
            esc_attr
esc_attr() は HTML 要素の属性(alt, value, title, class など)の値に出力する文字をエスケープする場合に使用します。
但し、href や src のような URI(URL) を指定可能な属性の場合は、XSS 対策として esc_attr() の代わりに esc_url() を使うようにします。(※ を参照)
機能的には esc_html() と同じですが、attribute_escape フィルタを通して出力されます。また esc_html() 同様、既にエンコードされている場合は二重にエンコードしません。
esc_attr( $text )
- パラメータ
 - $text(string):(必須) エスケープするテキスト
 
- 戻り値
 - HTML 文字参照でエンコードされたテキスト
 
<?php $name = ( isset( $_POST['name'] ) ) ? $_POST['name'] : ''; ?> <input type="text" name="name" value="<?php echo esc_attr( $name ); ?>">
※ href や src のような URI(URL) を指定可能な属性の場合は、XSS 対策として esc_attr() の代わりに esc_url() を使うようにします。
<!-- 正しい使い方 --> <img src="<?php echo esc_url( $src ); ?>" /> <!-- 問題はないが esc_attr() は冗長で不要 --> <img src="<?php echo esc_attr( esc_url( $src ) ); ?>" /> <!-- 誤った使い方(XSS 脆弱性あり) --> <img src="<?php echo esc_attr( $src ); ?>" />
以下は、_s(underscores) というスターター・テーマの header.php の記述の一部です。
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home"><?php bloginfo( 'name' ); ?></a>
また、属性の値に出力する際は、必ずクオート("")で囲む必要があります。
<!-- 正しい使い方 --> <input type="text" name="name" value="<?php echo esc_attr( $name ); ?>"> <!-- 誤った使い方(XSS 脆弱性あり)--> <input type="text" name="name" value=<?php echo esc_attr( $name ); ?>>
以下は esc_attr() のソースです。
エスケープ処理に関しては esc_html() と同じで、値を返す前に適用するフィルタが異なっています。
function esc_attr( $text ) {
    $safe_text = wp_check_invalid_utf8( $text );
    $safe_text = _wp_specialchars( $safe_text, ENT_QUOTES );
    /**
     * Filters a string cleaned and escaped for output in an HTML attribute.
     * Text passed to esc_attr() is stripped of invalid or special characters before output.
     * @since 2.0.6
     * @param string $safe_text The text after it has been escaped.
     * @param string $text      The text prior to being escaped.
     */
    return apply_filters( 'attribute_escape', $safe_text, $text );
}
            esc_url
esc_url() は URL のプロトコルのチェックや適切でない文字をエスケープ(または除去)して、URL を無害化します。URL を文字列で出力する場合や、URL を指定可能な属性(href や src)に値を出力する場合などで使用します。
この関数はホワイトリストに登録されているプロトコル(デフォルトでは http, https, ftp, ftps, mailto, news, irc, gopher, nntp, feed, and telnet)ではないものは拒絶し、無効なキャラクタを除外し、危険なキャラクタを削除します。「&」と「'」の文字はそれぞれ「&」と「'」に変換します。
(注意)対象の文字列の先頭に空白(半角や全角のスペース等)が入っていると空の文字列が返されます。カスタムフィールドの値などユーザーからの入力値など空白が入り込んでいる可能性がある値は trim() などで空白文字列を削除した方が良いと思います。
esc_url( $url, $protocols, $_context )
- パラメータ
 - 
                
- $url(string):(必須) 無害化しようとする URL
 - $protocols(array):(optional) 許可するプロトコルの配列(初期値: null)。指定しなければデフォルトで登録されているプロトコルのみ許可されます。
 - $_context (string):(optional) URLをどのように用いるかを指定(初期値: 'display')
 
 
- 戻り値
 - clean_urlフィルターを適用した後のクリーンアップされた URL。 $url が $protocols 以外のプロトコルを指定している場合、または $url に空の文字列が含まれている場合は、空の文字列が返されます。
 
以下は使用例です。
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">Home</a> <a href="<?php echo esc_url( home_url( '/cat/' ) ); ?>">カテゴリー</a>
home_url() は管理画面「設定」→「一般」の "サイトアドレス (URL)"の値を返す関数で、ホームURLからの相対パスを指定できます。
"サイトアドレス (URL)"が「http://example.com」の場合、以下のように表示されます。
<a href="http://example.com/">Home</a> <a href="http://example.com/cat/">カテゴリー</a>
また、絶対リンクと想定される文字列にプロトコルが含まれていない場合は、自動で http:// が補完されます(最後の「Link 5」の例)。
<?php
  echo '<a href="'. esc_url("http://example.com/01/?key=value&q's=foo").'">Link 1</a>';
  echo '<a href="'. esc_url("/sample/01/").'">Link 2</a>';
  echo '<a href="'. esc_url("#sample").'">Link 3</a>';
  echo '<a href="http://example.com'. esc_url("/sample/01/").'">Link 4</a>';
  echo '<a href="'. esc_url("sample/01/").'">Link 5</a>';
?>
          <a href="http://example.com/01/?key=value&q's=foo">Link 1</a> <a href="/sample/01/">Link 2</a> <a href="#sample">Link 3</a> <a href="http://example.com/sample/01/">Link 4</a> <a href="http://sample/01/">Link 5</a>
4番目の例の場合、「http://example.com」が自分のサイトのアドレスなら通常は、「home_url()」を使って以下のように記述します。
<?php echo '<a href="'. esc_url( home_url( '/sample/01/') ).'">Link 4</a>'; ?> <!-- 出力結果 --> <a href="http://www.example.com/sample/01/">Category</a>
先頭に / がない場合
以下のように記述した(先頭に / がない)場合、「http://」が自動的に補完されてしまうので(おそらく想定外の出力になるので)注意が必要です。
<?php
  echo '<a href="http://example.com/'. esc_url("sample/01/").'">Link 6</a>';
  echo '<a href="'. esc_url("../sample/01/").'">Link 7</a>';
?>
          <a href="http://example.com/http://sample/01/">Link 6</a> <a href="http://../sample/01/">Link 7</a>
登録されていないプロトコル
ホワイトリストに登録されていないプロトコルの場合は、空の文字列が返されます。
<?php
  echo '<a href="'. esc_url("mailto:info@exmple.com").'">Mailto</a>';
  echo '<a href="'. esc_url("tel:0123456789").'">TEL</a>';
  echo '<a href="'. esc_url("skype:abcd.efgh?call").'">Skype</a>';
  echo '<a href="'. esc_url("macappstores://itunes.apple.com/").'">Mac App Store</a>';
?>
          <a href="mailto:info@exmple.com">Mailto</a> <a href="tel:0123456789">TEL</a> <a href="">Skype</a> <a href="">Mac App Store</a>
プロトコルの追加
デフォルトで登録されていないプロトコルを使用すると、空の文字列が返されます。
<?php echo '<a href="'. esc_url("skype:abcd.efgh?call").'">Call Skype</a>'; ?>
            <a href="">Call Skype</a>
第二引数に許可するプロトコルの配列を指定できます。以下の場合は、skype プロトコルのみが許可されます。
echo '<a href="'. esc_url("skype:abcd.efgh?call" , array('skype')).'">Skype</a>';    
            以下は、デフォルトのプロトコルに「skype」と「macappstores」を追加した配列を指定する例です。(配列に許可したいプロトコルを指定することができます)
<?php
  $protocols = array('skype', 'macappstores', 'http', 'https', 'ftp', 'ftps', 'mailto', 'news', 'irc', 'gopher', 'nntp', 'feed', 'telnet');
  echo '<a href="'. esc_url("skype:abcd.efgh?call" , $protocols).'">Skype</a>';
  echo '<a href="'. esc_url("macappstores://itunes.apple.com/" , $protocols).'">Mac App Store</a>';
?>
            または、以下のようにデフォルトのプロトコルを拡張することもできます。
デフォルトのプロトコルの拡張
以下を functions.php に記述することで、デフォルトのプロトコルを拡張することができます。こうすれば、第二引数にプロトコルを指定しなくても追加したプロトコルが許可されます。
/**
 * 許可されているプロトコルを拡張
 * パラメータの $protocols :WordPress で許可されているデフォルトのプロトコルのリスト(配列)
 * return する $protocols:新しいプロトコルと追加して更新されたプロトコルのリスト(配列)
 */
function my_extend_allowed_protocols( $protocols ){
    $protocols[] = 'skype';
    $protocols[] = 'spotify';
    $protocols[] = 'macappstores';
    return $protocols;
}
add_filter( 'kses_allowed_protocols' , 'my_extend_allowed_protocols' );
            以下は esc_url() のソースです。
function esc_url( $url, $protocols = null, $_context = 'display' ) {
  $original_url = $url;
  if ( '' == $url ) {
    return $url;
  }
  $url = str_replace( ' ', '%20', $url );
  $url = preg_replace( '|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url );
  if ( '' === $url ) {
    return $url;
  }
  if ( 0 !== stripos( $url, 'mailto:' ) ) {
    $strip = array( '%0d', '%0a', '%0D', '%0A' );
    $url   = _deep_replace( $strip, $url );
  }
  $url = str_replace( ';//', '://', $url );
  /* If the URL doesn't appear to contain a scheme, we presume it needs http:// prepended (unless a relative link starting with /, # or ? or a php file).
   */
  if ( strpos( $url, ':' ) === false && ! in_array( $url[0], array( '/', '#', '?' ) ) &&
    ! preg_match( '/^[a-z0-9-]+?\.php/i', $url ) ) {
    $url = 'http://' . $url;
  }
  // Replace ampersands and single quotes only when displaying.
  if ( 'display' == $_context ) {
    $url = wp_kses_normalize_entities( $url );
    $url = str_replace( '&', '&', $url );
    $url = str_replace( "'", ''', $url );
  }
  if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) {
    $parsed = wp_parse_url( $url );
    $front  = '';
    if ( isset( $parsed['scheme'] ) ) {
      $front .= $parsed['scheme'] . '://';
    } elseif ( '/' === $url[0] ) {
        $front .= '//';
    }
    if ( isset( $parsed['user'] ) ) {
      $front .= $parsed['user'];
    }
    if ( isset( $parsed['pass'] ) ) {
      $front .= ':' . $parsed['pass'];
    }
    if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) {
      $front .= '@';
    }
    if ( isset( $parsed['host'] ) ) {
      $front .= $parsed['host'];
    }
    if ( isset( $parsed['port'] ) ) {
      $front .= ':' . $parsed['port'];
    }
    $end_dirty = str_replace( $front, '', $url );
    $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty );
    $url       = str_replace( $end_dirty, $end_clean, $url );
  }
  if ( '/' === $url[0] ) {
      $good_protocol_url = $url;
  } else {
    if ( ! is_array( $protocols ) ) {
      $protocols = wp_allowed_protocols();
    }
    $good_protocol_url = wp_kses_bad_protocol( $url, $protocols );
    if ( strtolower( $good_protocol_url ) != strtolower( $url ) ) {
      return '';
    }
  }
  /**
   * Filters a string cleaned and escaped for output as a URL.
   * @since 2.3.0
   * @param string $good_protocol_url The cleaned URL to be returned.
   * @param string $original_url      The URL prior to cleaning.
   * @param string $_context          If 'display', replace ampersands and single quotes only.
   */
  return apply_filters( 'clean_url', $good_protocol_url, $original_url, $_context );
}
            esc_url_raw
esc_url_raw() は URL をデータベースに格納するときに使う関数です。この関数は文字を HTML 実体にエンコードしません(それ以外は、esc_url() と同じ)。URL を保存するときやエンコードしない形で保存したいときはこの関数を使います。
esc_url_raw( $url, $protocols )
- パラメータ
 - 
                
- $url(string):(必須) 無害化しようとする URL
 - $protocols(array):(optional) 許可するプロトコルの配列(初期値: null)。指定しなければデフォルトで登録されているプロトコルのみ許可されます。
 
 
- 戻り値
 - 無害化された $url が返されます(文字を HTML 実体にエンコードしません)。
 
urlencode
urlencode() は文字列を URL エンコードします(PHP 関数)。クエリパラメータで使用する場合や URL に変数や関数が返す値を含めたりする場合は、URL エンコードします。
urlencode ( $str )
- パラメータ
 - $st(string):エンコードする文字列
 
- 戻り値
 - 「-」「_」「.」を除くすべての非英数文字が % 記号 (%)に続く二桁の数字で置き換えられ、 空白は + 記号(+)にエンコードされます。
 
- PHP マニュアル : urlencode
 
<?php
  $link = 'リンクパス';
  echo '<a href="'. esc_url('http://example.com/'). urlencode( $link ) . '/">Link</a>';
?>
          出力結果(日本語などのマルチバイト文字は、以下のように URL エンコードされます)
<a href="http://example.com/%E3%83%AA%E3%83%B3%E3%82%AF%E3%83%91%E3%82%B9/">Link</a>
urlencode_deep
urlencode_deep() は配列のすべての要素を URL エンコードします。
urlencode_deep( $value )
- パラメータ
 - $value(mixed):エンコードする配列または文字列
 
- 戻り値
 - エンコードされた配列または文字列
 
esc_textarea
esc_textarea() は textarea 要素の中で使えるように文字列をエンコード(エスケープ)する関数です。HTML で特別な意味を持つ文字(&、<、>、"、' )をエンコードし、textarea 以外でも使用できます。
esc_html() とは異なり、既にエンコードされている文字を二重にエンコードします。
また、無効な UTF-8 文字列はチェックしません。無効な UTF-8 文字列をチェックする必要がある場合は、sanitize_text_field() を使用することができます。
esc_textarea( $text )
- パラメータ
 - $text(string):(必須) エンコード(エスケープ)するテキスト
 
- 戻り値
 - HTML エンティティをエンコード済みのテキスト。
 
<?php $text = '<a href="about.html">'; ?> <textarea><?php echo esc_textarea( $text ); ?></textarea>
出力結果
<textarea><a href="about.html"></textarea>
既にエンコードされている文字を二重にエンコードします。
<?php $text = '&'; ?> <textarea><?php echo esc_textarea( $text ); ?></textarea>
出力結果
<textarea>&amp;</textarea>
以下は esc_textarea() のソースです。
PHP の htmlspecialchars() の実行結果に esc_textarea フィルタを適用した値を返しています。
function esc_textarea( $text ) {
  $safe_text = htmlspecialchars( $text, ENT_QUOTES, get_option( 'blog_charset' ) );
  /**
   * Filters a string cleaned and escaped for output in a textarea element.
   * @since 3.1.0
   * @param string $safe_text The text after it has been escaped.
   * @param string $text      The text prior to being escaped.
   */
  return apply_filters( 'esc_textarea', $safe_text, $text );
}
            タグやスクリプトの除去
PHP には、文字列から HTML および PHP タグを削除してくれる strip_tags() 関数がありますが、WordPress にも以下のようなタグやスクリプトを削除する便利な関数が用意されています。
sanitize_text_field
sanitize_text_field() はユーザーからの入力やデータベースから取得した文字を無害化(以下)します。
- 無効な UTF-8 をチェック
 - 独立した '<' 文字をエンティティーへ変換
 - タグをすべて除去
 - 改行・タブ・余分な空白を削除
 - オクテット('%' に続く 2 桁の 16 進数)を除去
 
sanitize_text_field( $str )
- パラメータ
 - $str(string ):(必須) 無害化される文字列
 
- 戻り値
 - 無害化された文字列
 
<?php
  $text = '<a href="about.html">リンク</a>
  <p>タグは<strong>全て削除</strong>されます。</p>
  <script>alert("hellow");</script>
  <これはタグではありませんが削除されます>
  <<  >>';
?>
<textarea><?php echo sanitize_text_field( $text ); ?></textarea>
          出力結果
<textarea>リンク タグは全て削除されます。 << >></textarea>
wp_kses
wp_kses() は指定した特定の HTML タグ以外を除去します。
KSES は悪意あるスクリプトを除去します。すべての信頼できない HTML (投稿文、コメント文など) は wp_kses() を通すべきです。
--日本語Codex データ検証より抜粋--
KSES は「KSES Strips Evil Scripts」の略です(Function Reference/wp kses)
wp_kses( $string, $allowed_html, $allowed_protocols )
- パラメータ
 - 
                
- $string(文字列):対象の文字列(必須)
 - $allowed_html(配列):許可するタグ(HTML 要素)とその属性(必須)
 - $allowed_protocols(配列):許可するプロトコル(オプション)
 
 
- 戻り値
 - 許可した以外のタグや属性を全て取り除いた文字列
 
第一引数に対象の文字列、第二引数に許可するタグとその属性を配列で指定します。以下は許可するタグと属性を配列で個々に指定する例です。
<?php
// 第二引数の指定例
$allowed_html = array(
  'a' => array(
    // 属性を残す場合はその属性を指定します
    'href' => array (),
    'target' => array()
  ),
  'br' => array(),
  'strong' => array(),
);
$text = '<a href="example.com" target="_blank" title="link">Link</a><br>改行
<p><strong><span>パラ</span>グラフ</strong></p>
<script>alert("hellow");</script><style> a {color:red;}</style>';
?>
<div><?php echo wp_kses($text, $allowed_html); ?></div>
          出力結果(許可した以外のタグや属性が全て取り除かれます)
<div><a href="example.com" target="_blank">Link</a><br>改行
<strong>パラグラフ</strong>
alert("hellow"); a {color:red;}</div>
          何度も使用する場合は、第二引数を functions.php に記述しておくと便利です。
//functions.php
$allowed_html = array(
  'a' => array(
    'href' => array (),
    'target' => array()
  ),
  'br' => array(),
  'strong' => array(),
);
          第二引数には、wp_kses_allowed_html() を使って WordPress で用意している許可するタグや属性のリストを指定することができます。
post を指定すると、投稿のページで許可されているタグが許可されます。
<?php echo wp_kses($text, wp_kses_allowed_html( 'post' )); ?>
wp_kses_post()
wp_kses_post() を使用すれば、投稿コンテンツに対して許可された HTML タグに基づいて、与えられたコンテンツをサニタイズ(無害化)します。
wp_kses_post( $data )
- パラメータ
 - $data (string):(必須) フィルターする投稿コンテンツ(文字列)
 
- 戻り値
 - フィルターされた投稿コンテンツ(文字列)。許可された HTML タグと属性はそのままにされます。
 
<?php
  $text = '<a href="example.com" target="_blank" title="link">Link</a><br>改行
  <p><strong><span>パラ</span>グラフ</strong></p>
  <script>alert("hellow");</script><style> a {color:red;}</style>';
?>
<div><?php echo wp_kses_post($text); ?></div>
          <div><a href="example.com" target="_blank" title="link">Link</a><br>改行
<p><strong><span>パラ</span>グラフ</strong></p>
alert("hellow"); a {color:red;}</div>
          wp_kses($text, wp_kses_allowed_html( 'post' )) や wp_kses( $text, 'post' ) と指定するのと同等のようです。
function wp_kses_post( $data ) {
    return wp_kses( $data, 'post' );
}
          srcset や sizes 属性が消える
get_the_post_thumbnail() で取得した img 要素のマークアップが含まれる場合、wp_kses_post() を使ってサニタイズすると、img 要素の srcset や sizes 属性が削除されます。
例えば、以下のようなアイキャッチ画像のマークアップは
<img width="300" height="225" src="http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1-300x225.jpg" class="attachment-medium size-medium wp-post-image" alt="Sample Post" style="max-width:225px;max-height:225px;" srcset="http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1-300x225.jpg 300w, http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1-1024x768.jpg 1024w, http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1-768x576.jpg 768w, http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1.jpg 1536w" sizes="auto, (max-width: 300px) 100vw, 300px">
wp_kses_post() を適用すると、srcset と sizes 属性が削除されて以下のように出力されます。
<img width="300" height="225" src="http://localhost/wp-sample/wp-content/uploads/2023/01/291678e33c68b8286.78582170-1536x1152-1-300x225.jpg" class="attachment-medium size-medium wp-post-image" alt="Sample Post" style="max-width:225px;max-height:225px">
代替策
img 要素の srcset や sizes 属性が削除されないようにサニタイズするには、wp_kses() を使い、第2引数の許可するタグや属性のリストに img 要素の srcset や sizes を追加します。
例えば、$content にアイキャッチ画像のマークアップが含まれる場合、以下のように記述できます。
wp_kses_allowed_html() に post を指定して、the_content() と同様の許可タグを取得して、それに img の srcset 属性と izes を追加しています。
$allowed_tags = wp_kses_allowed_html('post'); // デフォルトの許可タグを取得
$allowed_tags['img']['srcset'] = true; // 許可タグのリストに img の srcset 属性を追加
$allowed_tags['img']['sizes'] = true; // 許可タグのリストに img の sizes を追加
print(wp_kses($content, $allowed_tags));
            wp_kses_data()
wp_kses_data() を用いれば、コメントで許可される少数のタグのみを残すことができます。
wp_kses_data( $data )
- パラメータ
 - $data (string):(必須) フィルターするコンテンツ(文字列)
 
- 戻り値
 - HTML kses ルールを使用してサニタイズ(無害化)されたコンテンツ(文字列)
 
<?php
$text = '<a href="example.com" target="_blank" title="link">Link</a><br>改行
<p><strong><span>パラ</span>グラフ</strong></p>
<script>alert("hellow");</script><style> a {color:red;}</style>';
?>
<div><?php echo wp_kses_data($text); ?></div>
          <div><a href="example.com" title="link">Link</a>改行
<strong>パラグラフ</strong>
alert("hellow"); a {color:red;}</div>
          wp_kses($text, wp_kses_allowed_html('data')) と指定するのと同等のようです。
wp_kses_allowed_html
wp_kses_allowed_html() は指定されたコンテキストに合う「許可するタグやその属性のリスト」を返す関数です。
- パラメータ
 - $context(string|array):(オプション)タグを指定するためのコンテキスト。指定できる値は post、strip、entities、data または user_description、pre_user_description などの「field filter 名」です。( wp-includes/kses.php で関数の定義部分の switch ( $context ) に記述されています)
 
- 戻り値
 - コンテキストに合わせた許可するタグのリスト。タグ名をキーとして、属性名を値とする多次元配列。
 
| 指定値 | 説明 | 主な用途 | 
|---|---|---|
| post | ブログ投稿やコンテンツ向けの標準的な HTML タグを許可。wp_kses_post() と同じフィルター | 投稿本文、ウィジェットのテキスト、カスタムフィールド | 
| strip | すべてのタグを削除し、テキストのみを保持。wp_kses() を使って完全に HTML を除去したい場合に使用 | 投稿タイトル、コメントの一部など、完全にテキストのみを扱う場合 | 
| data | data-* 属性を含むタグを許可。wp_kses_data() のフィルターと同じ | JavaScript との連携が必要な要素(例: data-id などを含む動的コンテンツ) | 
| entities | HTML エンティティを許可しつつ、タグは基本的に許可しない。HTML の特殊文字を正しくエスケープして扱うためのモード | HTML をテキストとして扱う場合、エンティティのエスケープ処理 | 
以下はコンテキストに post を指定してその内容を var_dump() で確認する例です。
<?php
$allowed_tags = wp_kses_allowed_html( 'post' );
var_dump( $allowed_tags );
?>
/* 出力例
array(74) {
  ["address"]=>array(11) {
    ["aria-describedby"]=>bool(true)
    ["aria-details"]=>bool(true)
    ["aria-label"]=>bool(true)
    ["aria-labelledby"]=>bool(true)
    ["aria-hidden"]=>bool(true)
    ["class"]=>bool(true)
    ["id"]=>bool(true)
    ・・・中略・・・
  ["video"]=>array(20) {
    ["autoplay"]=>bool(true)
    ["controls"]=>bool(true)
    ["height"]=>bool(true)
  ・・・中略・・・
}
*/
          例えば、wp_kses_allowed_html( 'post' ) で取得した許可するタグのリストに img 要素の srcset や sizes を追加してサニタイズするには、以下のように記述できます。
$allowed_tags = wp_kses_allowed_html('post');
$allowed_tags['img']['srcset'] = true;
$allowed_tags['img']['sizes'] = true;
echo wp_kses($html_content, $allowed_tags);
          以下は、wp_kses() の第二引数に wp_kses_allowed_html( 'data' ) を使って許可するタグを指定する例です。
<?php echo wp_kses($text, wp_kses_allowed_html( 'data' )); ?>
以下は wp_kses_allowed_html( 'data' ) で許可されるタグと属性を出力して確認する例です。wp_kses_allowed_html( 'post' ) に比べて許可するタグが少ないのが確認できます。
<?php
  $allowed_tags = wp_kses_allowed_html( 'data' );
  var_dump( $allowed_tags );
?>
/* 出力結果
  array(14) {
    ["a"]=> array(2) {
      ["href"]=>bool(true)
      ["title"]=>bool(true)
    }
    ["abbr"]=>array(1) {
      ["title"]=>bool(true)
    }
    ["acronym"]=>array(1) {
      ["title"]=>bool(true)
    }
    ["b"]=>array(0) {}
    ["blockquote"]=>array(1) {
      ["cite"]=>bool(true)
    }
    ["cite"]=>array(0) {}
    ["code"]=>array(0) {}
    ["del"]=>array(1) {
      ["datetime"]=>bool(true)
    }
    ["em"]=>array(0) {}
    ["i"]=>array(0) {}
    ["q"]=>array(1) {
      ["cite"]=>bool(true)
    }
    ["s"]=>array(0) {}
    ["strike"]=>array(0) {}
    ["strong"]=>array(0) {}
  }
*/