はじめに
実務にて、フォームデータを URL 入力チェックするバリデーション(入力値の検証)を実装する作業があり、それを解決した情報になります。Web 開発の初心者、初学者の方にもわかりやすいように、ソースコードを編集してサンプルを公開しています、ご参考になれば幸いです。
検証環境
サンプル
- GitHub
- index.php:URL チェックと入力フォーム
解説
サンプルのソースコードを基に実装方法を説明します。
URL の形式チェック
URL(Uniform Resource Locator)とは、簡単に言うとインターネット上にある リソース を特定する場所のことです。
よく URI(Uniform Resource Identifier)を URL と言い方が違うだけで同じ意味だと勘違いしている人がいるので注意しましょう。
URI には、URL と URN(Uniform Resource Name)が含まれます。
さて、PHP で文字列が URL 形式(RFC 2396 準拠)かどうかを検証するには Filter 関数 の filter_var に 検証フィルタ の FILTER_VALIDATE_URL
を指定すると簡単です。
例えば、下記のような関数を実装すると良いでしょう。
function checkUrl(string $url): bool {
return filter_var($url, FILTER_VALIDATE_URL) !== false;
}
この関数は下記の文字列を URL 形式と判定します。
http://example.com
http://example.com/
https://example.com
https://example.com/
ssh://user@server
mailto:
mailto:test@example.com
mailto:test@example.com/
ftp://example.txt
ftp://example.txt/
下記の文字列は URL 形式ではないと判定します。
http://
https://
ssh://
example://
tel:000-0000-0000
FILTER_VALIDATE_URL
は下記のような URN に非対応です。
urn:ietf:rfc:2396
urn:oid:2.16.840
さらに下記のような IDN(Internationalized domain name)に非対応です。
https://日本語.jp
https://ﺁﺭﺍﻳﻴﺂالمهوس.
https://Кириллица.com
https://Ellenikó.xyz
因みに FILTER_VALIDATE_URL
は下記のような文字列も通過させてしまうので XSS(Cross Site Scripting)の脆弱性があります。filter_var の戻り値の扱いに注意しましょう。
http://localhost?<script>alert('XSS');</script>
上記の問題に対してサンプルコードでは bool 型 で返すように工夫しています。
また、filter_var の options に下記のような フィルターフラグ を指定することでより細かくデータをフィルタリングすることができます。
FILTER_FLAG_SCHEME_REQUIRED
: PHP 7.3.0 よりFILTER_VALIDATE_URL
に含まれるので非推奨、URL スキームが必須になります。FILTER_FLAG_HOST_REQUIRED
: PHP 7.3.0 よりFILTER_VALIDATE_URL
に含まれるので非推奨、ホスト名が必須になります。FILTER_FLAG_PATH_REQUIRED
: パスが必須になります。FILTER_FLAG_QUERY_REQUIRED
: クエリ文字列が必須になります。
特定の URL スキームのみ通過させたい場合、例えば http://
と https://
のみ通過させたい場合は下記のように preg_match で条件を追加すると簡単です。
function checkUrl(string $url): bool {
return filter_var($url, FILTER_VALIDATE_URL) !== false && preg_match('#\Ahttps?://#', $url);
}
下記の PCRE 正規表現構文 を記述しています。
#
:デリミタ\A
: エスケープシーケンス 検索対象文字列の始端https?://
: http://, https:// の場合にマッチ
他の URL スキームの場合も同様に制限することができます。
まとめ
URL 入力チェックには基本的に filter_var と preg_match を利用すれば簡単に実装することができます。
URN や IDN に対応させたい場合は少し工夫が必要です。
以上です。
おわりに
サンプルのソースコードを再利用する際は、要件定義やコーディング規約にお気を付けください。