MySQL / 18. Обработка ввода через Web с помощью MySQL

Загрузка в форму записи базы данных

Задача
Вы хотите вывести форму, используя в качестве начальных значений содержимое записей базы данных. Это позволит вам представить форму для редактирования записей.

Решение
Создавайте форму как обычно, только вместо использования ее обычных значений по умолчанию установите элементы формы в значения столбцов записи базы данных.

Обсуждение
Рассматриваемые ранее примеры создания полей формы или не задавали значений по умолчанию, или использовали значение по умолчанию из определения столбца ENUM или SET как умолчание для поля. Именно так обычно и создаются «пустые» формы, которые должен заполнить пользователь. Однако если речь идет о приложении, предлагающем веб-интерфейс для редактирования записи, то вы, вероятно, захотите, чтобы форма при открытии была заполнена содержимым существующей записи базы данных. В этом разделе рассказано о том, как это сделать.

Примеры этого раздела показывают, как создать форму для редактирования записей таблицы cow_order. Обычно пользователю предлагается выбрать, какую запись он будет редактировать. Мы же для простоты будем считать, что используется запись со значением id, равным 1, которая содержит следующее:

mysql> SELECT * FROM cow_order WHERE id = 1\G
*************************** 1. row ***************************
id: 1
color: Black & White
size: large
accessories: cow bell,nose ring
cust_name: Farmer Brown
cust_street: 123 Elm St.
cust_city: Katy
cust_state: TX

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

• Для элементов <input>, таких как переключатели и флажки, добавьте атрибут checked каждому элементу списка, совпадающему со значением столбца.

• Для элементов <select>, таких как всплывающие меню и прокручиваемые списки, добавьте атрибут checked каждому элементу списка, совпадающему со значением столбца.

• Для текстовых полей, представленных как элементы <input> типа text, установите атрибут value равным значению соответствующего столбца.

Например, 60-символьное поле для cust_name первоначально может быть установлено в значение Farmer Brown:

<input type="text" name="cust_name" value="Farmer Brown" size="60" />

Для представления элемента <textarea> установите его тело равным значению столбца. Создадим поле из трех 40-символьных строк:

<textarea name="cust_name" cols="40" rows="3">
Farmer Brown
</textarea>

• При редактировании записей удобно включать в форму уникальное значение, которое бы указывало, какую запись представляет содержимое формы, переданной пользователем. Можно сделать это при помощи скрытого поля – его значение не выводится для пользователя, но броузер возвращает его вместе со значениями всех остальных полей. Наша тестовая запись содержит столбец id со значением 1, поэтому скрытое поле может выглядеть так:

<input type="hidden" name="id" value="1" />

Следующий пример показывает, как вывести форму, в которой столбец id представлен как скрытое поле, color – как всплывающее меню, size – как группа переключателей, а accessories – как группа флажков. Информация  для пользователя отображается в текстовых полях ввода, за исключением столбца cust_state, выводимого в виде прокручиваемого списка с единичным выбором. Конечно, вы можете выбрать и другие варианты, например, показывать размеры (size) как всплывающее меню, а не как группу переключателей.

Сценарии примеров этого раздела называются edit_cow.pl, edit_cow.jsp и т. д. Рассмотрим процесс загрузки записи таблицы cow_table в форму редактирования при помощи сценария на основе CGI.pm.

1. Извлекаем значения столбцов для той записи, которую нужно загрузить в форму:

my $id = 1; # выбрать запись номер 1
my ($color, $size, $accessories,
$cust_name, $cust_street, $cust_city, $cust_state) =
$dbh->selectrow_array (
"SELECT
color, size, accessories,
cust_name, cust_street, cust_city, cust_state
FROM cow_order WHERE id = ?",
undef, $id);

2. Начинаем создавать форму:

print start_form (-action => url ());

3. Формируем скрытое поле, содержащее значение id, которое однозначно идентифицирует запись cow_order:

print hidden (-name => "id", -value => $id, -override => 1);

Аргумент override заставляет CGI.pm использовать значение, указанное в аргументе value, как скрытое значение поля. Это необходимо потому, что обычно CGI.pm пытается использовать значения переменных окружения сценария для инициализации полей формы, даже если значения передаются в вызовах генерирования полей. (CGI.pm пытается тем самым упростить повторное отображение формы с уже введенными пользователем значениями. Например, если вы обнаружите, что форма была запол-нена неверно, то можете повторно запросить ее и все исправить. Чтобы удостовериться в том, что элемент формы содержит указанное вами значение, необходимо запретить такое поведение.)

4. Создаем поля, описывающие параметры фигурок коров. Эти поля формируются так, как описывалось в рецептах 18.2 и 18.3, только значения по умолчанию берутся из содержимого записи 1. Код представляет color как всплывающее меню, size – как группу переключателей, а accessories – как группу флажков. Обратите внимание на то, что он разбивает значение accessories по запятым для создания массива значений, так как значение столбца может содержать несколько аксессуаров:

my $color_ref = $dbh->selectcol_arrayref (
"SELECT color FROM cow_color ORDER BY color");
print br (), "Cow color:", br ();
print popup_menu (-name => "color",
-values => $color_ref,
-default => $color,
-override => 1);
my $size_info = get_enumorset_info ($dbh, "cow_order", "size");
print br (), "Cow figurine size:", br ();
print radio_group (-name => "size",
-values => $size_info->{values},
-default => $size,
-override => 1,
-linebreak => 1);
my $acc_info = get_enumorset_info ($dbh, "cow_order", "accessories");
my @acc_val = (defined ($accessories)
? split (/,/, $accessories)
: () );
print br (), "Cow accessory items:", br ();
print checkbox_group (-name => "accessories",
-values => $acc_info->{values},
-default => \@acc_val,
-override => 1,
-linebreak => 1);

5. Создаем поля с информацией о клиенте. Они будут текстовыми полями ввода, за исключением штата, который выводится как прокручиваемый список с единичным выбором:

print br (), "Customer name:", br ();
print textfield (-name => "cust_name",
-value => $cust_name,
-override => 1,
-size => 60);
print br (), "Customer street address:", br ();
print textfield (-name => "cust_street",-value => $cust_street,
-override => 1,
-size => 60);
print br (), "Customer city:", br ();
print textfield (-name => "cust_city",
-value => $cust_city,
-override => 1,
-size => 60);
my @state_values;
my %state_labels;
my $sth = $dbh->prepare ("SELECT abbrev, name FROM states ORDER BY name");
$sth->execute ();
while (my ($abbrev, $name) = $sth->fetchrow_array ())
{
push (@state_values, $abbrev); # сохранить каждое значение в массиве
$state_labels{$abbrev} = $name; # сопоставить каждому значению название
}
print br (), "Customer state:", br ();
print scrolling_list (-name => "cust_state",
-values => \@state_values,
-labels => \%state_labels,
-default => $cust_state,
-override => 1,
-size => 6); # показывать 6 значений одновременно

6. Создаем кнопку отправки формы и завершаем форму:

print br (),
submit (-name => "choice", -value => "Submit Form"),
end_form ();

Процедура для других API будет такой же. Например, в странице JSP вы можете извлечь запись для редактирования и присвоить значения ее полей скалярным переменным так:

<c:set var="id" value="1" />
<sql:query var="rs" dataSource="${conn}">
SELECT
id, color, size, accessories,
cust_name, cust_street, cust_city, cust_state
FROM cow_order WHERE id = ?
<sql:param value="${id}" />
</sql:query>
<c:set var="row" value="${rs.rows[0]}" />
<c:set var="id" value="${row.id}" />
<c:set var="color" value="${row.color}" />
<c:set var="size" value="${row.size}" />
<c:set var="accessories" value="${row.accessories}" />
<c:set var="cust_name" value="${row.cust_name}" />
<c:set var="cust_street" value="${row.cust_street}" /><c:set var="cust_city" value="${row.cust_city}" />
<c:set var="cust_state" value="${row.cust_state}" />

Затем использовать эти значения для инициализации различных элементов формы, таких как:

• Скрытое поля для значения идентификатора:

<input type="hidden" name="id" value="<c:out value="${id}" />" />

• Всплывающее меню color:

<sql:query var="rs" dataSource="${conn}">
SELECT color FROM cow_color ORDER BY color
</sql:query>

Cow color:

<select name="color">
<c:forEach var="row" items="${rs.rows}">
<option
value="<c:out value="${row.color}" />"
<c:if test="${row.color == color}">selected="selected"</c:if>
><c:out value="${row.color}" /></option>
</c:forEach>
</select>

• Текстовое поле cust_name:


Customer name:

<input type="text" name="cust_name"
value="<c:out value="${cust_name}" />"
size="60" />

Статьи по MySQL на эту тему:

Ведение журнала Apache с помощью MySQL
Выполнение поиска и получение результатов
Журнал доступа к веб-странице
Использование ввода через Web для формирования запросов
Обработка загружаемых файлов