От rfc3986:
Зарезервированные символы
URIs включают в себя компоненты и подкомпоненты, которые разделяются символами в "зарезервированных" набор. Эти символы называются «зарезервированы», потому что они могут (или не могут) быть определены как разделители с помощью общего синтаксиса, каждого синтаксиса конкретной схемы или специфического для реализации синтаксиса алгоритма разыменования URI.
...
reserved = gen-delims/sub-delims
gen-delims = ":"/"/"/"?"/"#"/"["/"]"/"@"
sub-delims = "!"/"$"/"&"/"'"/"("/")"
/"*"/"+"/","/";"/"="
Цель зарезервированных символов является предоставление набора разграничения символов, которые отличаются от других данных в пределах URI. URI , которые отличаются заменой зарезервированного символа своим , соответствующим процентным октетом, не эквивалентны. Процентное кодирование зарезервированного символа или декодирование октета с процентом, который соответствует зарезервированному символу, изменит способ интерпретации URI большинством приложений.
...
URI, продуцирующие приложения должны октет данных процентов закодировать, что соответствуют символам в заповедной наборе, если эти символы специально не разрешены схемами URI для представления данных в этом компонента. Если зарезервированный символ найден в компоненте URI и , то никакой разделительной роли известен для этого символа, тогда он должен быть интерпретирован как представляющий октет данных, соответствующий этому кодированию символов в US-ASCII.
Так &
в URL должен быть закодирован, если это часть стоимости и не имеет нет, ограничивающей роли.
Вот простой фрагмент PHP кода с использованием функции urlencode()
:
<?php
$query_string = 'foo=' . urlencode($foo) . '&bar=' . urlencode($bar);
echo '<a href="mycgi?' . htmlentities($query_string) . '">';
?>