Как правильно URL-адрес кодировать строку в PHP?

97

Я создаю страницу поиска, где вы вводите поисковый запрос, и форма отправляется search.php?query=your query. Какая функция PHP является лучшей и которую я должен использовать для кодирования / декодирования поискового запроса?

Нажмите Голосовать за
источник
2
У вас возникли проблемы? Браузеры и PHP уже должны обрабатывать это автоматически (например, вставляя foo barтекстовое поле, создается foo+barв URL-адресе).
Феликс Клинг,
@Felix Я собираюсь вызвать скрипт поисковика, используяfile_get_contents
Click Upvote

Ответы:

183

Для запроса URI используйте urlencode/ urldecode; для чего-нибудь еще используйте rawurlencode/ rawurldecode.

Разница между urlencodeи в rawurlencodeтом, что

  • urlencodeкодируется в соответствии с application / x-www-form-urlencoded (пробел кодируется +), а
  • rawurlencodeкодируется в соответствии с простым Percent-Encoding (пробел кодируется %20).
Гамбо
источник
application / x-www-form-urlencoded - это просто специальный вариант Percent-Encoding, который применяется только для кодирования данных HTML-формы.
Gumbo
1
@ Click Upvote: их нельзя сравнивать таким образом. Формат application / x-www-form-urlencoded - это формат Percent-Encoding , за исключением того, что пробел кодируется с помощью +вместо %20. Кроме того, application / x-www-form-urlencoded используется для кодирования данных формы, тогда как Percent-Encoding имеет более общее применение.
Gumbo
12
rawurlencode () совместит с яваскриптом decodeURI () функцией
Клайв Патерсон
Всегда ли это правило эмпирическое? Я имею в виду, что когда мне нужно закодировать строку запроса, я всегда использую urldecode. Тогда как насчет пути URI (например /a/path with spaces/) и фрагмента URI (например #fragment). Должен ли я всегда использовать rawurldecodeдля этих двоих?
tonix
Хорошее практическое правило: пути (Like / my% 20folder /) идут с rawurlencode; но для полей POST и GET используйте urlencode(Like /? folder = my + folder) `
Соруш
22

Хитроумно названные urlencode () и urldecode () .

Однако вам не нужно использовать urldecode()переменные, которые появляются в $_POSTи $_GET.

Оливер Чарльзуорт
источник
4
не могли бы вы объяснить, почему urldecode () не следует использовать с $ _POST. потому что я занимаюсь этим с давних пор без каких-либо проблем.
sid
мне нужно кодировать основные параметры (например "name=b&age=c&location=d"), отправленные в файл PHP через AJAX?
oldboy
9

Вот мой вариант использования, который требует исключительного количества кодирования. Возможно, вы думаете, что это надумано, но мы запускаем это на производстве. По совпадению, это охватывает все типы кодирования, поэтому я публикую в качестве учебного пособия.

Описание варианта использования

Кто-то только что купил предоплаченную подарочную карту («жетон») на нашем сайте. У токенов есть соответствующие URL-адреса для их погашения. Этот клиент хочет отправить URL кому-нибудь по электронной почте. На нашей веб-странице есть mailtoссылка, которая позволяет им это сделать.

Код PHP

// The order system generates some opaque token
$token = 'w%a&!e#"^2(^@azW';

// Here is a URL to redeem that token
$redeemUrl = 'https://httpbin.org/get?token=' . urlencode($token);

// Actual contents we want for the email
$subject = 'I just bought this for you';
$body = 'Please enter your shipping details here: ' . $redeemUrl;

// A URI for the email as prescribed
$mailToUri = 'mailto:?subject=' . rawurlencode($subject) . '&body=' . rawurlencode($body);

// Print an HTML element with that mailto link
echo '<a href="' . htmlspecialchars($mailToUri) . '">Email your friend</a>';

Примечание: вышесказанное предполагает, что вы выполняете вывод в text/htmlдокумент. Если ваш тип выходного носителя - text/jsonпросто используйте, $retval['url'] = $mailToUri;потому что выходное кодирование обрабатывается json_encode().

Прецедент

  1. Запустите код на тестовом сайте PHP ( есть ли канонический, который я должен здесь упомянуть? )
  2. Нажмите на ссылку
  3. Отправить электронное письмо
  4. Получить электронное письмо
  5. Щелкните эту ссылку

Тебе следует увидеть:

"args": {
  "token": "w%a&!e#\"^2(^@azW"
}, 

И, конечно же, это JSON-представление $tokenвыше.

Уильям Энтрикен
источник
Эквивалентно и менее семантически (потому что mailto:это не HTTP) вы можете использовать $mailToUri 'mailto:?' . http_build_query(['subject'=>$subject, 'body'=>$body], null, '&', PHP_QUERY_RFC3986);.
Уильям Энтрикен
0

Вы можете использовать функции кодирования URL-адресов. PHP имеет

rawurlencode() 

функция

ASP имеет

Server.URLEncode() 

функция

В JavaScript вы можете использовать

encodeURIComponent() 

функция.

Амранур Рахман
источник
0

В зависимости от того, какой тип стандартной кодировки RFC вы хотите выполнить или если вам нужно настроить кодировку, вы можете создать свой собственный класс.

/**
 * UrlEncoder make it easy to encode your URL
 */
class UrlEncoder{
    public const STANDARD_RFC1738 = 1;
    public const STANDARD_RFC3986 = 2;
    public const STANDARD_CUSTOM_RFC3986_ISH = 3;
    // add more here

    static function encode($string, $rfc){
        switch ($rfc) {
            case self::STANDARD_RFC1738:
                return  urlencode($string);
                break;
            case self::STANDARD_RFC3986:
                return rawurlencode($string);
                break;
            case self::STANDARD_CUSTOM_RFC3986_ISH:
                // Add your custom encoding
                $entities = ['%21', '%2A', '%27', '%28', '%29', '%3B', '%3A', '%40', '%26', '%3D', '%2B', '%24', '%2C', '%2F', '%3F', '%25', '%23', '%5B', '%5D'];
                $replacements = ['!', '*', "'", "(", ")", ";", ":", "@", "&", "=", "+", "$", ",", "/", "?", "%", "#", "[", "]"];
                return str_replace($entities, $replacements, urlencode($string));
                break;
            default:
                throw new Exception("Invalid RFC encoder - See class const for reference");
                break;
        }
    }
}

Пример использования:

$dataString = "https://www.google.pl/search?q=PHP is **great**!&id=123&css=#kolo&email=me@liszka.com)";

$dataStringUrlEncodedRFC1738 = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_RFC1738);
$dataStringUrlEncodedRFC3986 = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_RFC3986);
$dataStringUrlEncodedCutom = UrlEncoder::encode($dataString, UrlEncoder::STANDARD_CUSTOM_RFC3986_ISH);

Выведет:

string(126) "https%3A%2F%2Fwww.google.pl%2Fsearch%3Fq%3DPHP+is+%2A%2Agreat%2A%2A%21%26id%3D123%26css%3D%23kolo%26email%3Dme%40liszka.com%29"
string(130) "https%3A%2F%2Fwww.google.pl%2Fsearch%3Fq%3DPHP%20is%20%2A%2Agreat%2A%2A%21%26id%3D123%26css%3D%23kolo%26email%3Dme%40liszka.com%29"
string(86)  "https://www.google.pl/search?q=PHP+is+**great**!&id=123&css=#kolo&email=me@liszka.com)"

* Узнайте больше о стандартах RFC: https://datatracker.ietf.org/doc/rfc3986/ и urlencode vs rawurlencode?

DevWL
источник