PHP и HTML

PHP и HTML тесно взаимодействуют: PHP умеет генерировать HTML, а HTML умеет передавать информацию PHP. Перед чтением вопросов в этом разделе важно понимать, как получать переменные извне PHP. Страницы руководства по этой теме содержат много примеров.

Какое кодирование или декодирование я должен выполнять при передаче значения через форму или URL-адрес?

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

  • Интерпретация HTML. Чтобы задать произвольную строку, вы должны заключить её в двойные кавычки и использовать функцию htmlspecialchars() для кодирования.

  • URL: URL-адрес состоит из нескольких частей. Если вы хотите, чтобы данные были восприняты как один элемент, нужно закодировать их функцией urlencode().

Пример #1 Скрытый элемент HTML-формы

<?php

echo '<input type="hidden" value="' . htmlspecialchars($data) . '" />'."\n";

?>

Замечание: Кодировать перменную $data функцией urlencode() неправильно, поскольку кодировать данные urlencode() это обязанность браузера. Популярные браузеры делают это правильно. Заметьте, что это произойдёт независимо от метода (например, GET или POST). Это заметно только в случае GET-запроса, поскольку POST-запросы обычно скрыты.

Пример #2 Данные, которые редактирует пользователь

<?php

echo "<textarea name='mydata'>\n";
echo
htmlspecialchars($data) . "\n";
echo
"</textarea>";

?>

Замечание: Браузер показывает данные как предполагалось, потому что браузер интерпретирует экранированные HTML-символы. При отправке через GET- или POST-метод браузер закодирует (urlencoded) данные для передачи, а PHP декодирует (urldecoded). Поэтому не нужно выполнять какое-либо кодирование или декодирование, всё обрабатываются автоматически.

Пример #3 В URL

<?php

echo '<a href="' . htmlspecialchars("/nextpage.php?stage=23&data=" .
urlencode($data)) . '">' . "\n"
;

?>

Замечание: На самом деле вы подделываете HTML-запрос GET, поэтому необходимо вручную закодировать (urlencode()) данные.

Замечание: Вам надо применить функцию htmlspecialchars() к полному URL-адресу, потому что URL-адрес появляется как значение HTML-атрибута. При этом браузер сначала раскодирует всё значение (операция, обратная действию функции htmlspecialchars()) и затем передаст URL. PHP поймёт URL-адрес правильно, поскольку вы закодировали данные функцией urlencode(). Вы заметите, что символ & в URL-адресе заменяется на мнемонику &amp;. Хотя большинство браузеров это исправит, если вы забудете об этом, но всё же это не всегда возможно. Поэтому, даже если ваш URL-адрес не динамический, нужно закодировать его функцией htmlspecialchars().

Я пытаюсь использовать <input type="image">, но переменные $foo.x и $foo.y недоступны. Значение $_GET['foo.x'] тоже не существует. Где они?

При отправке формы, вместо стандартной кнопки отправки допустимо использовать изображение с тэгом вроде такого:

<input type="image" src="image.gif" name="foo" />
Когда пользователь кликает по изображению, серверу будет послана сопутствующая форма с двумя дополнительными переменными: foo.x и foo.y.

Поскольку имена foo.x и foo.y не разрешены в PHP, они автоматически преобразовываются в foo_x и foo_y. То есть точки заменяются на подчёркивания. Таким образом, вы обращаетесь к этим переменным так же, как и к любым другим, описанным в разделе о получении переменных извне PHP. Например, $_GET['foo_x'].

Замечание:

Пробелы в именах переменных запроса преобразовываются в подчёркивания.

Как создать массивы в HTML <form>?

Чтобы браузер передал результат <form> в PHP-скрипт как массив, элементы <input>, <select> или <textarea> называют следующим образом:

<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyArray[]" />
Обратите внимание на квадратные скобки после имени переменной: они делают переменную массивом. Разработчику доступна группировка элементов в массив за счёт присваивания одинакового имени разным элементам:
<input name="MyArray[]" />
<input name="MyArray[]" />
<input name="MyOtherArray[]" />
<input name="MyOtherArray[]" />
Это создаст два массива, MyArray и MyOtherArray, которые браузер передаст PHP-скрипту. Можно также задать конкретные ключи для массивов:
<input name="AnotherArray[]" />
<input name="AnotherArray[]" />
<input name="AnotherArray[email]" />
<input name="AnotherArray[phone]" />
Массив AnotherArray теперь будет содержать ключи 0, 1, email и phone.

Замечание:

Определять ключи массивов в HTML необязательно. Если вы не установите ключи, массив заполнится в порядке появления элементов в форме. Первый пример будет содержать ключи 0, 1, 2 и 3.

Также смотрите Функции для работы с массивами и Переменные извне PHP.

Как получить все результаты из HTML-тега select с атрибутом multiple?

HTML-тег select с атрибутом multiple разрешает пользователю выбрать элементы из списка. Эти элементы затем передаются обработчику формы. Проблема в том, что они переданы с одним и тем же именем. Например:

<select name="var" multiple="yes">
Каждая выбранная опция поступит обработчику формы как:
var=option1
var=option2
var=option3
      
Каждая опция будет перезаписывать содержимое предыдущей переменной $var. Решение — использовать функцию PHP «массив из элемента формы». Как в следующем примере:
<select name="var[]" multiple="yes">
Это говорит PHP рассматривать переменную $var как массив и каждое присваивание значения для var[] добавляет элемент в массив. Первым элементом будет $var[0], следующим — $var[1] и т. д. Можно использовать функцию count(), чтобы определить, сколько элементов было выбрано, а функцию sort() — для сортировки массива опций, если это необходимо.

Заметьте, если вы используете JavaScript, есть риск того, что запись [] в имени элемента вызовет проблемы, если вы пытаетесь обращаться к элементу по имени. Вместо этого указывайте числовой идентификатор элемента формы или возьмите имя переменной в одинарные кавычки и используйте его как индекс массива элементов, например:

variable = document.forms[0].elements['var[]'];
      

Как передать переменную из JavaScript в PHP?

Поскольку JavaScript — обычно клиентская технология, а PHP, как правило, серверная, и поскольку HTML — протокол «без состояния», эти два языка не умеют обмениваться переменными напрямую.

Однако можно передавать переменные между ними. Один из способов добиться этого — сгенерировать JavaScript-код из PHP и принудительно обновлять браузер, посылая определённые переменные обратно PHP-скрипту. Пример показывает, как это сделать — он разрешает PHP-коду захватывать высоту и ширину экрана, что обычно возможно только на стороне клиента.

Пример #4 Генерирование JavaScript из PHP

<?php

if (isset($_GET['width']) AND isset($_GET['height'])) {
// Выводим переменные с размерами
echo "Ширина экрана: " . $_GET['width'] . "<br />\n";
echo
"Высота экрана: " . $_GET['height'] . "<br />\n";
} else {
// Передаём переменные с размерами
// (сохраняем оригинальную строку запроса
// — POST-переменные нужно будет передавать другим способом)

echo "<script>\n";
echo
" location.href = \"{$_SERVER['SCRIPT_NAME']}?{$_SERVER['QUERY_STRING']}"
. "&width=\" + screen.width + \"&height=\" + screen.height;\n";
echo
"</script>\n";
exit;
}

?>

add a note add a note

User Contributed Notes 7 notes

up
1
murphy
4 years ago
The scenario:

1. There is a php script which (possibly complemented by a direct written HTML code) consrtucts a HTML page via its echo command, based on whatever algoritmus eventually based on supplementary data from server files or databases.

2. This php script leads to data being saved into string variable(s), which (possibly) can contain arbitrary characters, including control codes (newline, tab...), HTML special characters (&,<...) and non-ASCII (international) characters.

3. These non-ASCII characters are UTF-8 encoded, as well as the HTML page (I do highly recommend) *)

4. The values of these PHP string variables have to be transferred into javascript variables for further processing by javascript (or exposing these values in HTML directly)

The problem:

it is not safe to PHP-echo such variables into HTML (javascript) directly, because some of characters possily contained in them cause malfunction of the HTML. These strings need some encoding/escaping in order to become strings of non-conflicting characters

The solution

There may be a big lot of ways of this encoding. The following one seems to me the easiest one:
The PHP variable with unpredictable value can originate from some file, as an example (or from user input as well):

$variable=file_get_content(...)

1. Convert all bytes of that string into hex values and prepend all hex-digit-pairs with %

$variable_e=preg_replace("/(..)/","%$1",bin2hex($variable))

The new variable is now guarantied to contain only %1234567890abcdefABCDEF chracters (e.g. %61%63%0a...) and can safely be directly echoed into HTML:

var variable="<?php echo $variable_e;?>" //that's NOT all folks

But now the value is still encoded. To get the original value of the variable, it has te be decoded: *)

var variable=decodeURIComponent("<?php echo $variable_e;?>")

The value of the variable is now the same as the original value.

*) I have no idea about non-UTF-8 encoded pages/data, espetially how the decodeURIComponent works in such a case, because i have no reason to use other encodings and handle them as highly deprecatad.

WARNING: this approach is not (generally) safe against code injection. I highly recommend some further check (parsing) of the value depending on the particular case.

P.S. For very large amount of data, I would recomment to save them into file on the PHP side (file_put_content) and read them by javascript via HTTP Request.

I use this approach as it needs one line of code on server as well as client side. I do agree with arguement that not all chaeacters have to be encoded.

Do not enjoy my possibly stupid solution, if you have a better idea

murphy
up
-4
Anonymous
3 years ago
I think the last example on this page may have a XSS vulnreability, e.g. sending the query string ?a="+alert('XSS')+" might cause alert('XSS') to be executed in the browser. The problem with that is that " will be percent encoded by the browser, but there could be some way to bypass the percent encoding and i think it's not good to rely on the percent encoding for security.
up
-5
Anonymous
3 years ago
There is also a very easy XSS with the width and height parameters - they should be passed through htmlspecialchars
up
-21
starbugfourtytwo at gmail dot com
5 years ago
Why use such a complicated example for js to php? why not do this..so we can understand:

javascript:

const variable = "A"

php:

do whatever it takes to get A from javascript
up
-24
smileytechguy at smileytechguy dot com
6 years ago
The (at least that I've found) best way to pass data from PHP to JS is json_encode.  Doing so will convert arrays, strings, numbers, etc. as best as possible.

<?php
$myInt
= 7;
// a bunch of special characters to demonstrate proper encoding
$myString = <<<EOF
" ' ; &\ $
EOF;
$myArr = [1, "str", 2];
$myAssocArr = ["foo" => "bar"];
?>

<script>
var myInt = <?= json_encode($myInt) ?>;
var myString = <?= json_encode($myString) ?>;
var myArr = <?= json_encode($myArr) ?>;
var myAssocArr = <?= json_encode($myAssocArr) ?>;
</script>

This will render the following JS code, which correctly stores the variables:
<script>
var myInt = 7;
var myString = "\" ' ; &\\ $";
var myArr = [1,"str",2];
var myAssocArr = {"foo":"bar"};
</script>

Do note that there are no "s or anything like that around the json_encode output; json_encode handles that for you.
up
-58
jetboy
18 years ago
While previous notes stating that square brackets in the name attribute are valid in HTML 4 are correct, according to this:

http://www.w3.org/TR/xhtml1/#C_8

the type of the name attribute has been changed in XHTML 1.0, meaning that square brackets in XHTML's name attribute are not valid.

Regardless, at the time of writing, the W3C's validator doesn't pick this up on a XHTML document.
up
-63
Jay
10 years ago
If you have a really large form, be sure to check your max_input_vars setting.  Your array[] will get truncated if it exceeds this.  http://www.php.net/manual/en/info.configuration.php#ini.max-input-vars
To Top