フォームなどから入力を受け取る場合、
「入力された文字列が正しいURLかどうか確かめたい」
という場面は結構あると思います。
そこでPHPである文字列が正しいURL形式化チェックする方法をまとめました。
URLチェックを行う2つの方法
そのチェック方法とは次の2つ
- 正規表現を使ってチェック
- filter_var関数を使ってチェック
正規表現を使うのが一般的かもですが、PHPだと filter_var という値をフィルターする関数も用意されているのでそちらを使用した方が楽です。
この2つの具体的なやり方やコード例は次の通り
1.正規表現を使ってチェック
URLかどうかにマッチする正規表現は色々な書き方があります。
ここで使うのは単純にアスキー文字だけのURLにマッチする次の正規表現です。
1 |
https?:\/{2}[\w\/:%#\$&\?\(\)~\.=\+\-]+ |
この正規表現は正規表現サンプル集に載っていたサンプル例を参考に書かせていただきました。
ちなみにプロトコルは http または https にしか対応していません。もし ftp や file なども対応させたいなら (https?|ftp|file) などのようにパイプでつなげればOKです。
そして次がこの正規表現を使ったURL形式チェックのコード例
1 2 3 4 5 6 7 8 9 10 11 |
$url = 'https://example.com/'; $pattern = '/https?:\/{2}[\w\/:%#\$&\?\(\)~\.=\+\-]+/'; $result = preg_match( $pattern, $url ); if( $result ){ /** URLが"正しい"場合の処理 */ print_r('$url is correct URL.'); }else{ /** URLが"正しくない"場合の処理 */ print_r('$url is NOT correct URL.'); } |
このコードではpreg_match関数を使い、 $pattern がマッチするかどうかで正しいURLか判定しています。
preg_match関数の返り値は、マッチした場合は 1 、しなかった場合は 0 、エラーが起きた場合は FALSE の値が返ってきます。なので $result そのものをif分の条件式にして問題ありません。
あと基本的なことですがPHPの正規表現は文字列で囲む必要があることにも注意です。
参考記事 : PHPでの正規表現の表現方法や使い方まとめ
ちなみにこの方法は 日本語を含むURLは途中までしかマッチできない、という制限があります。
例えば次が日本語を含むURLがどこまでマッチするか確かめているコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$url = 'https://example.com/テスト/'; $pattern = '/https?:\/{2}[\w\/:%#\$&\?\(\)~\.=\+\-]+/'; $result = preg_match( $pattern, $url, $matches ); if( $result ){ /** URLが"正しい"場合の処理 */ print_r('$url is correct URL.'); print_r( $matches[0] ); /// => https://example.com/ }else{ /** URLが"正しくない"場合の処理 */ print_r('$url is NOT correct URL.'); } |
上コードでは https://example.com/テスト/ 自体は $pattern にマッチします。
しかし $matches[0] を調べてみると https://example.com/テスト/ の テスト/ は含まれていないので、日本語はマッチしていないことが分かるはずです。
以上が正規表現でURLかどうか判別するテクニック
正規表現を自分で用意しなければならない点と汎用的に利用するなら関数化が必要なところが少し面倒だと思います。
2.filter_var関数を使ってチェック
PHPでは値をフィルタリングするのに filter_var という関数が使えます。
この関数の使い方は値を $data 、フィルタIDを $filter とすると次のような書き方
1 |
filter_var( $data, $filter ); |
返り値は成功した場合はフィルタリングされたデータ、失敗すると FALSE が返ってきます。
URLかどうかをフィルタリングする場合は FILTER_VALIDATE_URL というフィルタIDを渡すことで正規表現を使わずとも簡単にURLチェックが可能です。
例えば次がURLの判定チェックを filter_var を使って行っているコード例
1 2 3 4 5 6 7 8 9 |
$url = 'https://example.com/'; if( filter_var( $url, FILTER_VALIDATE_URL ) ){ /** URLが"正しい"場合の処理 */ print_r('$url is correct URL.'); }else{ /** URLが"正しくない"場合の処理 */ print_r('$url is NOT correct URL.'); } |
上コードの filter_var( $url, FILTER_VALIDATE_URL ) がURLチェックを行っている部分
正規表現を使う場合と比べて自分であれこれ書く必要がないのでシンプルに書けます。
ただし FILTER_VALIDATE_URL による判定だと次の制限がある点に注意
- ASCIIオンリーのURLのみ対応
- 国際化ドメイン名は失敗する
アスキー文字のみのURLを正しいとみなすので日本語を含むURLは "正しくない" と判定されてしまいます。正規表現でもそうですが、国際化したURLに対応するのはさすがに厳しいみたいですね。
補足 : IPアドレスやメルアドを形式チェックするには・・
ここまででURLの形式チェック方法を紹介してきました。
正規表現をゴリゴリ書くよりfilter_var関数を使う方が簡単だと思います。
ちなみにfilter_var関数ではIPアドレスやメルアドの形式チェックも可能です。
詳しいやり方やコード例は次記事で解説した通り
フォーム送信されたメルアドをチェックする場合なんかに使えそうです。
ここまでのまとめ
ここまでで紹介したPHPでのURLチェック方法は次の2つ
- 正規表現を使った方法
パターンを自分で用意して preg_match にマッチするか確かめるだけ
ただしPHPではfilter_var関数を使う方が簡単なので使うメリットはほぼなし - filter_var関数を使った方法
フィルタIDに FILTER_VALIDATE_URL を使えばURLのみフィルタリングできる
正規表現を使うよりコードも簡潔で分かりやすくなる。こっちを使うのがベスト
URLの形式チェックをするならfilter_var関数を使うのが圧倒的に楽です。
ただしどちらの方法も国際化ドメインや日本語を含むURLに対応できないことに要注意。正しいと認められるのはアスキー文字を含むURLのみです。