Как кодировать url только символы, не содержащие ASCII URL в PHP, но оставлять незашифрованные зарезервированные символы?
У меня есть URL-адрес, который выглядит так (обратите внимание на символы "):
http://tinklarastis.omnitel.lt/kokius-aptarnavimo-kanalus-klientui-siulo-„omnitel"-1494
Я получаю его от парсера SimplePie, если это имеет значение. Теперь, если вы попытаетесь перейти к этому конкретному URL-адресу в своем браузере и скопировать его из адресной строки, вы получите URL-адрес с символами, отличными от ASCII percent кодируются:
http://tinklarastis.omnitel.lt/kokius-aptarnavimo-kanalus-klientui-siulo-%E2%80%9Eomnitel%E2%80%9C-1494
Я пытаюсь понять, как я могу имитировать такое же преобразование в PHP. Я не могу просто использовать urlencode()
или urlrawencode()
, поскольку они кодируют оба символа без символа ASCII и зарезервированные символы, тогда как в моем случае зарезервированные символы (/? &, и т.д.) должны оставаться такими, какие они есть.
До сих пор я видел только решения, которые включали разделение URL-адреса на куски между зарезервированными символами, а затем с помощью urlencode()
, но это кажется мне взломанным, и я надеюсь там более элегантное решение. Я пробовал различные варианты iconv()
, mb_convert_encoding()
, но пока не добился успеха.
Ответы
Ответ 1
После небольшого исследования я пришел к выводу, что нет никакого способа сделать это на PHP (однако, другие языки, такие как python/perl, похоже, имеют функции именно для этого варианта использования). Это функция, с которой я пришел (обеспечивает кодирование фрагмента пути URL-адреса):
function url_path_encode($url) {
$path = parse_url($url, PHP_URL_PATH);
if (strpos($path,'%') !== false) return $url; //avoid double encoding
else {
$encoded_path = array_map('urlencode', explode('/', $path));
return str_replace($path, implode('/', $encoded_path), $url);
}
}
Ответ 2
У меня есть простая однострочная строка, которую я использую для кодирования на месте только для не-ASCII символов, используя preg_match_callback:
preg_replace_callback('/[^\x20-\x7f]/', function($match) {
return urlencode($match[0]);
}, $url);
Обратите внимание, что анонимная функция поддерживается только в PHP 5. 3+.
Ответ 3
Я думаю, что это будет делать то, что вы хотите.
<?php
$string = 'http://tinklarastis.omnitel.lt/kokius-aptarnavimo-kanalus-klientui-siulo-„omnitel"-1494/?foo=bar&fizz=buzz';
var_dump(filter_var($string, FILTER_SANITIZE_STRING, FILTER_FLAG_ENCODE_HIGH));
Это поможет вам:
$ php test.php
string(140) "http://tinklarastis.omnitel.lt/kokius-aptarnavimo-kanalus-klientui-siulo-„omnitel“-1494/?foo=bar&fizz=buzz"
Ответ 4
Эта функция может помочь:
function sanitizeUrl($url)
{
$chars = '$-_.+!*\'(),{}|\\^~[]`<>#%";/?:@&=';
$pattern = '~[^a-z0-9' . preg_quote($chars, '~') . ']+~iu';
$callback = create_function('$matches', 'return urlencode($matches[0]);');
return preg_replace_callback($pattern, $callback, $url);
}
Ответ 5
function cyrillicaToUrlencode($text){
return $line = preg_replace_callback('/([а-яё])/ui',
function ($matches) {
return urlencode($matches[0]);
},
$text);
}
echo cyrillicaToUrlencode("https://test.com/Москваёtext1Воронежtext2Москваёtext3yМоскваё___-Москваё");
Вернется - https://test.com/%D0%9C%D0%BE%D1%81%D0%BA%D0%B2%D0%B0%D1%91text1%D0%92%D0%BE%D1% 80% D0% BE% D0% BD% D0% B5% D0% B6text2% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% D1% 91text3y% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% D1% 91___-% D0% 9C% D0% BE% D1% 81% D0% BA% D0% B2% D0% B0% D1% 91