PHPでecho
などを使って表示させる際に使うhtmlspecialchars()
(長いw)はみなさんも使ってるかと思います。
ただ、つい付け忘れたり、ダブって付けたりしているケースもあります。
セキュリティ上、出力時には必ず付けたい関数ですが、長ったらしくてソースが汚くもなりますね。
今回はこの関数の使い方と、短縮してたった一文字で簡単に使う方法をご紹介します。
目次
htmlspecialchars関数でHTMLエンティティ化
HTMLエンティティ化とは、>
(大なり)や""
(ダブルクォート)など、特殊な意味を持つ特殊文字を、特殊な意味を持たない単なる文字列に変換することです。
フォームなどでユーザーが悪意のあるスクリプトを送信しようとするのを防いでくれたりするので、セキュリティ上必須となっています。
説明文だけではよく分かりませんので、とりあえずサンプルから見てみましょう。
HTMLエンティティ化した場合としない場合の比較
1 2 3 4 5 |
// HTMLエンティティ化した場合 echo htmlspecialchars('<a href="#">HTMLエンティティ化する。</a>'); // HTMLエンティティ化しない場合 echo '<a href="#">HTMLエンティティ化しない。</a>'; |
HTMLエンティティ化した場合の表示
<a href=”#”>HTMLエンティティ化する。</a>
HTMLエンティティ化しない場合の表示
上記2つを比べると、以下のような違いがあります。
- HTMLエンティティ化した場合
htmlのリンクタグがそのまま文字列として表示され、クリックしても動作しない。 - HTMLエンティティ化しない場合
リンクのアンカーテキストだけが表示され、実際にクリックできる。
ブラウザのソース表示で見比べてみると分かりやすいでしょう。
HTMLエンティティ化した場合のソース表示
<a href="#">HTMLエンティティ</a>
HTMLエンティティ化していない場合のソース表示
<a href=”#”>HTMLエンティティ化しない。</a>
上記の例はリンクのタグですが、これがもし個人情報やセキュリティ上重要な情報を抜き取るプログラムだったり、同じリンクでも悪意のあるサイトにリンクするなど、悪意のあるプログラムが仕込まれたら…と考えるとゾッとしますね。
こういった手法をXXS(クロスサイトスクリプティング)と言います。
HTMLエンティティ化することで、上記サンプルのようにタグを無効化し、単なる文字列として出力してくれるので、悪意のあるスクリプトを仕込まれても大丈夫なんですね。
変換対象の文字列
HTMLエンティティ化される文字列は以下の5文字のみです。
&
(アンパサンド)=>&
""
(ダブルクォート)=>"
(ENT_NOQUOTES
が設定されていない場合のみ)''
(シングルクォート)=>'
(あるいは'
)(ENT_QUOTES
が設定されている場合のみ)<
(小なり)=><
>
(大なり)=>>
htmlspecialchars関数の構文
htmlspecialchars (エンティティ対象文字列, (フラグ, エンコード(これらは省略可)))
フラグ
この関数のフラグには、変換する文字列を指定した定数を指定します。
フラグ一覧(抜粋)
定数名 | 説明 |
---|---|
ENT_CONPAT(初期値) | ダブルクオートは変換するが、シングルクオートは変換しない。 |
ENT_QUOTES | シングルクオートとダブルクオートを共に変換する。 |
ENT_NOQUOTES | シングルクオートとダブルクオートは共に変換しない。 |
エンコード
UTF-8などの文字エンコードを指定します。
サンプル
1 |
echo htmlspecialchars('<a href="#">HTMLエンティティ化する。</a>', ENT_QUOTES, 'UTF-8'); |
ENT_QUOTES
が一般的なフラグ指定になります。
出力する際のHTMLエンティティ化は、必須事項として覚えておきましょう。
HTMLエンティティを元に戻す関数
使ったことはありませんが、HTMLエンティティを元に戻す関数もあります。
htmlspecialchars_decode 関数
1 |
echo htmlspecialchars_decode('<a href="#">HTMLエンティティを元に戻す。</a>', ENT_QUOTES); |
上記のようにリンクタグが蘇りましたね。
htmlspecialchars を簡略化する
htmlspecialchars
と毎回入力するのは長くて骨が折れますし、ソースもごちゃごちゃになります。
1 2 3 4 |
echo htmlspecialchars('ようこそ', ENT_QUOTES, 'UTF-8'); echo htmlspecialchars('こんにちは', ENT_QUOTES, 'UTF-8'); echo htmlspecialchars('こんばんは', ENT_QUOTES, 'UTF-8'); echo htmlspecialchars('さようなら', ENT_QUOTES, 'UTF-8'); |
これを毎回入力しないように、独自に関数化して、簡略化しちゃいましょう。
あの長い関数名をたった一文字に簡略化
1 2 3 4 5 6 7 |
// 関数化する function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } // 関数化したので、"h" の一文字だけでHTMLエンティティ化できるようになる echo h('<a href="#">HTMLエンティティ化する。</a>'); |
<a href=”#”>HTMLエンティティ化する。</a>
上記のように関数化することで、たった一文字でエンティティ化できるようになりました。
だいぶスッキリしましたね。
関数の仕組みはまた別の機会に勉強するとして、まずはコピーして動かしてみましょう。
関数専用のファイルを作りメンテナンス性アップ
何ページもあるPHPファイル全てに上記のように簡略化する関数を記述してもいいですが、同じ関数を何ページにも記述するのもムダですね。
そこで、以下のように外部ファイル化して、引っ張ってくるようにしましょう。
functions.php
1 2 3 4 |
// 関数だけを記述するPHPファイル function h($s) { return htmlspecialchars($s, ENT_QUOTES, 'UTF-8'); } |
読み込みたいPHPファイル
1 2 3 4 5 |
// まずfunctions.phpを読み込む require_once('functions.php'); // そして使う echo h('<a href="#">HTMLエンティティ化する。</a>'); |
上記のようにrequire_once()
を使うことで、外部ファイルを引っ張ってくることができます。
全ページに関数を記述するよりスマートですね。
フラグやエンコードが変わった場合でも、functions.php
の記述を書き換えるだけで全ページに反映されるためメンテナンス性にも優れるでしょう。
この関数に限らず、共通で使うコードは外部ファイル化して効率化したいですね。