Как правильно создавать HTML-ссылки в PHP? - PullRequest
0 голосов
/ 27 марта 2019

Этот вопрос касается правильного использования rawurlencode , http_build_query & htmlspecialchars .

До сих пор мой стандартный способ создания HTML-ссылки в vanilla PHP был таким:

$qs = [
    'foo' => 'foo~bar',
    'bar' => 'bar foo',
];
echo '<a href="?' . http_build_query($qs) . '">Link</a>';

Недавно я узнал, что это не на 100% правильно. Вот несколько вопросов:

  • http_build_query по умолчанию использует PHP_QUERY_RFC1738 вместо PHP_QUERY_RFC3986 . RFC3986 - это стандартный и замененный RFC1738, который в PHP хранится только для устаревшего использования.
  • В то время как «специальные» символы HTML в ключе и значении будут закодированы в процентное представление, разделитель аргументов будет амперсандом. В большинстве нормальных ситуаций это не будет проблемой, но иногда ваше имя ключа может быть quot;, и тогда ваша ссылка станет недействительной:

    $qs = [
        'a' => 'a',
        'quot;' => 'bar',
    ];
    echo '<a href="?' . http_build_query($qs) . '">Link</a>';
    

    Приведенный выше код сгенерирует эту ссылку: ?a=a"%3B=bar!
    IMO это означает, что функция http_build_query должна вызываться с учетом контекста с 3-м аргументом &amp; в HTML и с & в header('Location: ...');. Другой вариант - пропустить через htmlspecialchars перед отображением в HTML.

  • Руководство по PHP для urlencode (, которое давно не рекомендуется использовать, IMO ) предлагает кодировать только часть значения строки запроса и затем передавать весь запрос строка до htmlentities перед отображением в HTML. Это выглядит очень неправильно для меня; ключевая часть все еще может содержать запрещенные символы URL.

    $query_string = 'foo=' . urlencode($foo) . '&bar=' . urlencode($bar);
    echo '<a href="mycgi?' . htmlentities($query_string) . '">';
    

Мой вывод - сделать что-то вроде этого:

$qs = [
    'a' => 'a',
    'quot;' => 'bar foo',
];
echo '<a href="?' . http_build_query($qs, null, '&amp;', PHP_QUERY_RFC3986) . '">Link</a>';

Каков рекомендуемый способ создания HTML-ссылок в PHP? Есть ли более простой способ, чем я придумал? Я пропустил какие-то важные моменты?

1 Ответ

0 голосов
/ 26 июля 2019

Поскольку никто не смог дать ответ за последние 4 месяца, вот мои выводы подытожены.

Как динамически создавать ссылки HTML со строкой запроса?

Если вам нужно создать строку запроса для использования в HTML-ссылке (например, <a href="index.php?param1='.$value.'">Link</a>), тогда вы должны использовать http_build_query. Эта функция принимает 4 параметра, первый из которых представляет собой массив / объект данных запроса. По большей части остальные 3 параметра не имеют значения.

$qs = [
    'a' => 'a',
    'quot;' => 'bar foo',
];
echo '<a href="?' . http_build_query($qs) . '">Link</a>';

Однако, вы все равно должны передать выходные данные функции через htmlspecialchars, чтобы правильно кодировать &. «Хороший фреймворк сделает это автоматически, как и {{}} Ларавела»

echo '<a href="?' . htmlspecialchars(http_build_query($qs)) . '">Link</a>';

В качестве альтернативы вы можете передать третий аргумент http_build_query как '&amp;', оставив второй null. Это будет использовать &amp; вместо &, что htmlspecialchars будет делать.

О пробелах .
Для использования в данных формы (то есть в строках запроса) пробел должен быть закодирован как +, а в любом другом месте он должен быть закодирован как %20, например. new%20page.php?my+field=my+val. Это необходимо для обеспечения обратной сопоставимости со всеми браузерами. Вы можете использовать более новый RFC3986, который будет кодировать пробелы как %20, и он будет работать во всех распространенных браузерах, а также соответствовать современным стандартам.

echo '<a href="?' . http_build_query($qs, null, '&amp;', PHP_QUERY_RFC3986) . '">Link</a>';

rawurlencode против urlencode

Для любой части URL до ? следует использовать rawurlencode. Например:

$subdir = rawurlencode('blue+light blue');
echo '<a href="'.$subdir.'/index.php">rawurlencode</a>';

Если в приведенном выше примере вы используете urlencode, ссылка будет разорвана. urlencode имеет очень ограниченное использование и его следует избегать.

Не передавайте весь URL через rawurlencode. Разделители / и другие специальные символы в URL не должны кодироваться, если они должны выполнять свою функцию.


Сноска

Не существует общего соглашения о лучших методах использования http_build_query, за исключением того факта, что его следует передавать через htmlspecialchars, как и любой другой вывод в контексте HTML.

Laravel использует http_build_query($array, null, '&', PHP_QUERY_RFC3986)

CodeIgniter использует http_build_query($query)

Symfony использует http_build_query($extra, '', '&', PHP_QUERY_RFC3986)

Тонкий использует http_build_query($queryParams)

CakePHP использует http_build_query($query)

Веточка использует http_build_query($url, '', '&', PHP_QUERY_RFC3986)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...