Создание многостраничного сценария CGI

Проблема

Требуется написать сценарий CGI, который бы возвращал броузеру несколько страниц. Допустим, вы хотите написать сценарий CGI для работы с базой данных продуктов. Он должен выводить несколько форм: общий список продуктов, формы для добавления новых и удаления существующих продуктов, для редактирования текущих атрибутов продуктов и т. д. Многостраничный сценарий CGI образует простейший вариант «электронного магазина».

Решение

Сохраните информацию о текущей странице в скрытом поле.

Комментарий

Модуль CGI позволяет легко генерировать устойчивые скрытые поля. Функция hidden возвращает HTML-код скрытого элемента и использует его текущее значение в том случае, если ей передается только имя элемента:
use CGI qw(:standard);
print hidden("bacon");
Отображаемая страница («Общий список продуктов», «Список заказанных продуктов», «Подтверждение заказа» и т. д.) выбирается по значению скрытого поля. Мы назовем его .State, чтобы избежать возможных конфликтов с именами других полей. Для перемещения между страницами используются кнопки, которые присваивают .State имя новой страницы. Например, кнопка для перехода к странице «Checkout» создается так:
print submit(-NAME => ".State", -VALUE => "Checkout");
Для удобства можно создать вспомогательную функцию:
sub to_page { return submit( -NAME => ".State", -VALUE => shift ) }
Чтобы выбрать отображаемый код, достаточно проверить параметр . State:
$page = param(".State") || "Default";
Код, генерирующий каждую страницу, размещается в отдельной подпрограмме. Вообще говоря, нужную подпрограмму можно выбирать длинной конструкцией
if ... elsif ... elsif:
if ($page eq "Default") {
  front_page();
} elsif ($page eq "Checkout")  {
    checkout();
  } else {
      no_such_page();  # Если .State ссылается на несуществующую страницу
    }
Получается некрасивое, громоздкое решение. Вместо этого следует использовать хэш, ассоциирующий имя страницы с подпрограммой. Это еще один из вариантов реализации С-подобной конструкции switch на Perl.
%States = (
            'Default'  => \&front_page,
            'Shirt'    => \&shirt,
            'Sweater'  => \&sweater,
            'Checkout' => \&checkout,
            'Card'     => \&credit_card,
            'Order'    => \&order,
            'Cancel    => \&front__page,
          );
if ($States{$page}) {
  $States{$page}->()       # Вызвать нужную подпрограмму
} else {
    no_such_page();
  }
На каждой странице найдется несколько устойчивых элементов. Например, страница для заказа футболок должна сохранить количество заказанных товаров, даже если пользователь переходит на страницу для заказа кроссовок. Для этого подпрограмма, генерирующая страницу, вызывается с параметром, который определяет, является ли данная страница активной. Если страница не является активной, возвращаются лишь значения скрытых полей для любых устойчивых данных:
while (($state, $sub) = each %States) {
  $sub->( $page eq $state );
}
Оператор сравнения eq возвращает true, если страница является активной, и false в противном случае. Подпрограмма, генерирующая страницу, принимает следующий вид:
sub t_shirt  {
  my $active = shift;
  unless ($active) {
    print hidden("size"), hidden("color");
    return;
  }
  print p("You want to buy a t-shirt?");
  print p("Size: ", popup_menu("size", [ qw(XI_ L M S XS) ]));
  print p("Color:", popup_menu("color", [ qw(Black White) ]));
  print p( to_page("Shoes"), to_page("Checkout") );
}
Поскольку все подпрограммы генерируют HTML-код, перед вызовом необходимо вывести заголовок HTTP и начать HTML-документ и форму. Это позволит использовать стандартные колонтитулы для всех страниц, если мы захотим. Следующий фрагмент предполагает, что у нас имеются процедуры standard_header и standard_footer для вывода верхних и нижних колонтитулов страниц:
print header("Program Title"), begin_html();
print standard_header(), begin_form();
while (($state, $sub) = each %States) {
  $sub->( $page eq $state );
}
print standard_footer(), end_form(), end_html();
Кодирование цены в форме будет ошибкой. Вычисляйте цены на основании значений скрытых элементов и как можно чаще проверяйте информацию. Например, сравнение со списком существующих продуктов позволяет отбросить явно неразумные заказы.
Скрытые данные обладают большими возможностями, чем cookies, поскольку вы не можете твердо рассчитывать на поддержку cookies или на то, что броузер согласится принять их.

См. также




2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: