<% ASP на блюдечке %>.
Выбор аэропорта назначения (index.asp)
Для облегчения организации программного доступа к нашей базе данных, вынесем его в отдельный ASP-скрипт и будем «включать» его в тело каждого из последующих скриптов по мере необходимости:
<% Option explicit Dim conn Set conn = Server.CreateObject("ADODB.Connection") conn.open "DRIVER={Microsoft Access Driver (*.mdb)};DBQ=" & Server.Mappath("AirTickets.mdb") & ";" %>
Соединение с базой данных выполним наиболее простым и компактным образом (не забудьте разместить файл базы данных "AirTickets.mdb" в корневом каталоге сайта, так как Server.Mappath будет возвращать именно этот путь).
Теперь можно приступить к опросу нашего клиента. Согласитесь, что для начала неплохо было бы его поприветствовать:
… <card id="splash" ontimer="#card1" title="Welcome to"> <timer value="20"/> <p align="center"><br /> <img src="logo.wbmp" alt="WAP AirLines"/> </p> </card> …
Данная карта и будет приветствовать наших клиентов, показывая заставку из файла logo.wbmp, а если ей это не удастся, то заменит иллюстрацию альтернативной надписью "WAP AirLines", поле чего (по истечении двух секунд) будет загружаться карта «card1» палубы:
… <card id="card1" title="Flight to:"> <% SQLquery = "SELECT * FROM Destinations" ‘ Выборка всех строк таблицы Destinations set rsDestinations = conn.Execute(SQLquery) if rsDestinations.eof then ‘ Если таблица не содержит ни одной rsDestinations.close ‘ строки set rsDestinations = nothing ‘ то закрыть соединение с базой данных Response.write("<p>Sorry, this flight is not available now!") Response.write("<br /><anchor title='") ‘ и выдать сообщение о невозможности Response.write("ReStart'") ‘бронирования авиабилетов Response.write(">Go Home to Restart-><go href='") Response.write("index.asp'") Response.write("/></anchor>") Response.write("</p></card></wml>") Response.end end if %> <p><br /> <select name='TheCity'> <% Do while not rsDestinations.eof ‘В цикле отобразить в качестве элементов списка все аэропорты назначения response.write("<option value='" & rsDestinations("CityID") & "'>" & rsDestinations("City") & "</option>" & vbcrlf) rsDestinations.MoveNext Loop %> </select> <anchor title="Proceed!">Proceed-> <go href="Date.asp" method="get"> <!-- Обеспечить переход к следующему этапу опроса —- > <postfield name="TheCity" value="$(TheCity)" /> <!—Передав идентификатор выбранного пользователем города из списка-- > </go> </anchor> </p> <% rsDestinations.close set rsDestinations = nothing %> </card> …
Как видите, WML-страница формируется из базы данных в основном посредством ASP-метода response.write, отображающего список городов (значение полей rsDestinations("City") таблицы). Заметьте, что в качестве возвращаемого значения списка выбора select фигурирует значение именно ключевого поля первой таблицы — rsDestinations("CityID").
Далее выбранное пользователем значение передается в следующий скрипт (Date.asp) с помощью якоря Proceed.
Выбор даты и времени вылета (Dates.asp)
Скрипт Date.asp, в свою очередь, организует список из всех возможных значений дат и времени вылета рейсов, соответствующий значению выбранного города на основании полученного значения.
Для этого в первую очередь необходимо считать значение, введенное пользователем на предыдущем этапе:
<% … City = Request("TheCity") … %> Затем считать из первой таблицы название выбранного города в переменную, с тем чтобы показать его клиенту в дальнейшем:
<% … SQLQuery = "SELECT * FROM Destinations WHERE CityID = " & Request("TheCity") set rsCity = conn.Execute(SQLQuery) Set CityName = rsCity("City") … %>
После этого необходимо считать из второй таблицы все соответствующие значения и сформировать список из них:
<% … SQLQuery = "SELECT * FROM Dates WHERE CityID = " & Request("TheCity") set rsDates = conn.Execute(SQLQuery) … %>
Аналогично предыдущему случаю здесь и во всех последующих скриптах следует подумать о возможном отсутствии значений в таблице:
<% … if rsDates.eof then rsDates.close set rsDates = nothing Response.write("<p>Sorry, this flight is not available now!") Response.write("<br /><anchor title='") Response.write("ReStart'") Response.write(">Go Home to Restart-><go href='") Response.write("index.asp'") Response.write("/></anchor>") Response.write("</p></card></wml>") Response.end end if … %>
Теперь покажем клиенту название города, который он выбрал, и предоставим ему возможность выбрать дату и время вылета: <p><br />Flight to:<%=CityName%> <br />At: <select name='DateTime'> <% Do while not rsDates.eof response.write("<option value='" & rsDates("DatesID") & "'>" & rsDates("FlightDate") & ", " & rsDates("FlightTime") & "</option>" & vbcrlf) rsDates.MoveNext Loop %> </select>
Как видно, поля списка формируются из сочетаний дат и времени полей второй таблицы. Здесь, так же как и в первом случае, фигурирует значение ключевого поля таблицы «Dates»:
rsDates("DatesID").
Передадим в следующий скрипт (Flight.asp) два значения: название города назначения и ключевое значение, соответствующее выбранному пользователем значению времени вместе с датой во второй таблице:
<anchor title="Proceed!">Proceed-> <go href="Flight.asp" method="get"> <postfield name="City" value="<%=CityName%>" /> <postfield name="DateTime" value="$(DateTime)" /> </go> </anchor>
Покажем надпись перехода к предыдущему экрану с помощью следующего элемента:
<do type="prev" label="Previous"> <prev/> </do>
Выбор атрибутов рейса (Flight.asp)
Теперь пришло время выяснить, имеются ли билеты на выбранный клиентом рейс. Конечно, данный момент — не самый удачный для этого (по-хорошему это необходимо делать на каждом этапе регистрации выбранных пользователем значений, что потребует ввода полей с количеством оставшихся билетов во все таблицы), но для лучшего усвоения материала настоящей статьи мы не будем загромождать наши скрипты дополнительными проверками, а таблицы — дополнительными полями.
Получим значения, переданные предыдущим скриптом, и считаем их:
… <% … Dim TheDateTime Set TheCity = Request("City") Set TheDateTime = Request("DateTime") … %>
Выберем из таблицы дат и времени рейсов значение, соответствующее номеру выбранного пользователем поля, и считаем в переменные соответствующие значения даты и времени:
… <% SQLQuery = "SELECT * FROM Dates WHERE DatesID = " & Request("DateTime") set rsDateTime = conn.Execute(SQLQuery) Set FDate = rsDateTime("FlightDate") Set FTime = rsDateTime("FlightTime") … %>
Теперь из третьей таблицы выберем строки, соответствующее значениям времени и дате, выбранным клиентом на предыдущем этапе:
… <% SQLQuery = "SELECT * FROM Flights WHERE TimesID = " & Request("DateTime") set rsFlights = conn.Execute(SQLQuery) … %>
Покажем пользователю выбранные им значения и огранизуем список выбора класса и цены авиабилетов:
… <p><br />Flight to:<%=TheCity%> <br />At: <%=FDate%>, <%=FTime%><br /> <select name='FlightID'> <% Do while not rsFlights.eof response.write("<option value='" & rsFlights("FlightsID")+900 & "'>" & "A-" & rsFlights("Company") & "-" & rsFlights("Price2") & "USD" & "</option>" & vbcrlf) response.write("<option value='" & rsFlights("FlightsID") & "'>" & "B-" & rsFlights("Company") & "-" & rsFlights("Price1") & "USD" & "</option>" & vbcrlf) rsFlights.MoveNext Loop %> </select>
Элементы списка формируются из аббревиатуры названия авиакомпании rsFlights("Company"), цен билетов rsFlights("Price1") и rsFlights("Price2") для и первого второго классов соответственно. Однако здесь имеется один нюанс: поскольку здесь, как и в предыдущих случаях, значение, введенное пользователем, определяется по номеру строки в таблице, то невозможно определить, какое из двух значений класса и цены билета выбрал пользователь — эти значения являются элементами одной и той же строки. Во избежание этого будем прибавлять заведомо большое число к значению, введенному пользователем в том случае, если был выбран билет класса «A». Например, 900.
И наконец, передадим в последний скрипт проверки подтверждения все ранее введенные пользователем значения:
<anchor title="Proceed!">Proceed-> <go href="Order.asp" method="get"> <postfield name="City" value="<%=TheCity%>" /> <postfield name="Date" value="<%=FDate%>" /> <postfield name="Time" value="<%=FTime%>" /> <postfield name="FlightID" value="$(FlightID)" /> </go> </anchor> …
Подтверждение бронирования (Order.asp)
Покажем пользователю все значения, которые он выбрал, и попросим подтверждения на размещение брони:
Прочитаем значения, переданные скрипту в переменные:
<% … Set TheCity = Request("City") Set TheDate = Request("Date") Set TheTime = Request("Time") Set TheFlight = Request("FlightID") … %>
Если значение номера строки в таблице атрибутов рейса (третья таблица) больше 900, то от значения следует отнять 900, чтобы получить реальное значение номера выбранной пользователем строки, что, собственно, и означает, что пользователем был выбран билет класса «А».
<% … If TheFlight > 900 Then TheFlight = TheFlight — 900 TheClass = "A" Else TheClass = "B" End If … %>
Выберем те строки из таблицы с атрибутами рейсов, значение поля числа оставшихся билетов которых не отрицательно и идентификационный номер которых соответствует номеру, переданному предыдущим скриптом, затем считаем соответствующие значения (номер рейса, тип воздушного судна, аббревиатура названия авиакомпании, цена) в переменные:
<% … SQLQuery = "SELECT * FROM Flights WHERE Tickets > 0 AND FlightsID = " & TheFlight Set rsFlights = conn.Execute(SQLQuery) … Set FNum = rsFlights("FlightNo") Set PType = rsFlights("PlaneType") Set Comp = rsFlights("Company") If TheClass = "A" Then Set Price = rsFlights("Price2") Else Set Price = rsFlights("Price1") End If %>
Отобразим полученные значения, запросим имя клиента для последующего внесения в базу данных и передадим их последнему скрипту — скрипту регистрации заказа в системе:
<p> Flight No:<%=FNum%> <br /> To: <%=TheCity%> <br /> At: <%=TheDate%>, <%=TheTime%> <br /> Company: <%=Comp%> <br /> On plane: <%=PType%> <br /> Ticket class: <%=TheClass%> <br /> Ticket price: <%=Price%> USD <br /> …
Запрос ввода имени имеет два ограничения:
имя не может быть пустым, максимальная длина имени — 10 символов.
… Your name (*): <br/> <input name="username" emptyok="false" maxlength="10" /> <anchor title="Order">Order Now!-> <go href="Update.asp" method="get"> <postfield name="City" value="<% =TheCity%>" /> <postfield name="Date" value="<% =TheDate%>" /> <postfield name="Time" value="<% =TheTime%>" /> <postfield name="FNum" value="<% =FNum%>" /> <postfield name="Class" value="<% =TheClass%>" /> <postfield name="PType" value="<% =PType%>" /> <postfield name="Comp" value="<% =Comp%>" /> <postfield name="FID" value="<% =TheFlight%>" /> <postfield name="Price" value="<% =Price%>" /> <postfield name="UserName" value="$(username)" /> </go> </anchor> <do type="prev" label="Back"> <prev/> </do> </p>
Регистрация заказа в системе и выдача клиенту идентификатора (Register.asp)
Наконец можно зарегистрировать бронь клиента в базе данных. Для этого создадим таблицу (назовем ее Orders), в которую будем записывать заказы клиентов.
Теперь считаем значения всех переданных параметров в переменные:
<card id="card1" title="Order Complete:"> <% Dim SQLUpdate, SQLInsert, SQLQuery, rsOrders Dim TheFlight, TheCity, TheDate, TheTime, FNum, PType, Comp, TheClass, Price, RegCode, UName Set TheCity = Request("City") Set TheDate = Request("Date") Set TheTime = Request("Time") Set FNum = Request("FNum") Set TheClass = Request("Class") Set PType = Request("PType") Set Comp = Request("Comp") Set TheFlight = Request("FID") Set Price = Request("Price") Set UName = Request("UserName") … %>
Проверим, ввел ли клиент свое имя; если нет, то выдадим предупреждение и перенаправим его в предыдущий скрипт.
<% … If UName = "" Then Response.write("<p>You didn't enter your name!") Response.write("<br />Press 'Back' and enter it, please.<do type='") Response.write("prev'") Response.write(" label='") Response.write("Back'") Response.write("><prev/>") Response.write("</do></p></card></wml>") Response.end Else … %>
Обновим значение числа оставшихся билетов в таблице атрибутов рейсов, а именно — уменьшим это значение на 1:
<% … SQLUpdate = "UPDATE Flights SET Tickets = Tickets — 1 WHERE FlightsID =" & TheFlight conn.Execute(SQLUpdate) … %>
И добавим новую строку к таблице заказов (Orders):
<% … SQLInsert = "INSERT INTO Orders (City, FlightDate, FlightTime, FlightNo, TicketClass, TicketPrice, PlaneType, Company , UserName ) VALUES ('" & TheCity & "', '" & TheDate & "', '" & TheTime & "', '" & FNum & "', '" & TheClass & "', '" & Price & "', '" & PType & "', '" & Comp & "', '" & UName & "')" conn.Execute(SQLInsert) … %>
Выберем из таблицы заказов самый последний элемент (упорядочивание по убыванию значений столбца-счетчика OrderID позволит нам получить указатель на все элементы таблицы, самое первое значение которого укажет на строку, введенную в самую последнюю очередь, то есть введенную только что):
<% … SQLQuery = "SELECT * FROM Orders ORDER BY OrderID DESC" Set rsOrders = conn.Execute(SQLQuery) Set RegCode = rsOrders("OrderID") End If %>
Покажем пользователю его регистрационный код:
… <p> Thank you, <%=UName%> <br /> Your reg. Id: <%=RegCode%> <br /> <do type="prev" label="Previous"> <prev/> </do> <anchor title="Home">Home <go href="index.asp" /> </anchor> …
И предложим перейти к началу:
… </p> <% rsOrders.close set rsOrders = nothing %> </card>
Заключение
В заключение хотелось бы сориентировать разработчиков WAP-приложений и сайтов в Интернете. Дело в том, что автор настоящей статьи провел не один день за Интернетом в поисках всевозможных WAP-сайтов и советует, в частности, посетить:
Много полезных ресурсов (книги, справочная информация, часто задаваемые вопросы, ссылки, статьи …) — http://www.wap-resources.net/
- Сайт поддержки разработчиков компании Ericsson — http://www.ericsson.se/developerszone/index.asp
- Сайт-форум компании Nokia для разработчиков — http://www.forum.nokia.com/main.html
- WAP-новости, дискусcии, программное обеспечение, обучение, справочные материалы — http://www.wirelessdevnet.com
- Сайт знаменит серией довольно популярных online-учебников:
- Один из самых крупных WAP-форумов для разработчиков — http://www.wapforum.org/
- Новостной сайт по WAP — http://wap.net/
- Много теоретических основ WAP — http://www.gsmworld.com/technology/wap.html
- Wap Development Toolkit компании DSR — http://www.wap.net/devkit/
- Полезная вводная лекция по WAP — http://www.iec.org/tutorials/wap/
- Книга знаменитого издательства O’Reilly «Learning WML & WMLScript» — http://www.oreilly.com/catalog/learnwml/
- Online-версия третей главы книги — http://www.oreilly.com/catalog/learnwml/chapter/ch03.html
КомпьютерПресс 11'2000