Как url-кодировать только не-ASCII символы URL в PHP, но оставить зарезервированные символы незашифрованными? - PullRequest
12 голосов
/ 23 марта 2012

У меня есть URL, который выглядит следующим образом (обратите внимание на символы „„):

http://tinklarastis.omnitel.lt/kokius-aptarnavimo-kanalus-klientui-siulo-„omnitel“-1494

Я получаю его от парсера SimplePie, если это имеет значение. Теперь, если вы попытаетесь перейти по этому конкретному URL в своем браузере и скопировать его из адресной строки, вы получите URL с символами, не входящими в ASCII процентное кодирование :

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(), но пока безуспешно.

Ответы [ 5 ]

10 голосов
/ 25 ноября 2014

У меня есть простая однострочная строка, которую я использую для кодирования на месте только для не-ASCII символов, используя preg_match_callback:

preg_replace_callback('/[^\x20-\x7f]/', function($match) {
    return urlencode($match[0]);
}, $url);

Обратите внимание, что анонимная функция поддерживается только в PHP 5.3 +.

9 голосов
/ 05 июня 2012

Немного изучив, я пришел к выводу, что в 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 голосов
/ 20 марта 2013

Эта функция может помочь:

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);
}
2 голосов
/ 29 марта 2012

Я думаю, что это будет делать то, что вы хотите.

<?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-&#226;&#128;&#158;omnitel&#226;&#128;&#156;-1494/?foo=bar&fizz=buzz"
0 голосов
/ 26 мая 2018
...