Проверить URI для RFC 3986 довольно просто. Вы можете использовать регулярное выражение вроде:
/^ # Start at the beginning of the text
([a-z][a-z0-9\*\-\.]*):// # The scheme
(?: # Userinfo (optional)
(?:(?:[\w\.\-\+!$&'\(\)*\+,;=]|%[0-9a-f]{2})+:)*
(?:[\w\.\-\+%!$&'\(\)*\+,;=]|%[0-9a-f]{2})+@
)?
(?: # The domain
(?:[a-z0-9\-\.]|%[0-9a-f]{2})+ # Domain name or IPv4
|(?:\[(?:[0-9a-f]{0,4}:)*(?:[0-9a-f]{0,4})\]) # or IPv6
)
(?::[0-9]+)? # Server port number (optional)
(?:[/|\?]
(?:[\w#!:\.\?\+=&@!$'~*,;/\(\)\[\]\-]|%[0-9a-f]{2}) # The path (optional)
*)?
$/xi
Но это не работает для международных символов, подобных тем, которые встречаются в международных доменных именах. Например, http: // 例 え. テ ス ト / メ イ ン ペ ー ジ.
Используя что-то вроде
filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED);
для них тоже не работает. Проблема связана с используемыми персонажами.
Есть ли хороший способ проверить URI в PHP?






С preg_match \ pL будет соответствовать любой букве юникода. Поэтому замените a-z на \ pL. И 0-9 с \ pN. См. Детали регулярного выражения для получения дополнительной информации.