Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Замечание. Описание синтаксиса языка SQL смотрите в гл




Описание синтаксиса языка SQL смотрите в гл. 3, а многочисленные примеры использования объектов класса TQuery — в разделе, посвященном реализации информационной системы фирмы "Два кирпича", настоящей главы.

 

Автоматическое создание HTML-таблиц на основе выполненного запроса

Объекты класса TQuery преобразуют данные, полученные в результате SQL-запроса, во внутреннее табличное представление. Данные можно из этой таблицы извлекать и модифицировать, однако для того, чтобы их можно было отобразить в виде таблицы, необходимо либо напрямую генерировать HTML-код, либо воспользоваться специальным объектом — экземпляром класса TQueryTabieProducer. Этот объект, взаимодействуя с источником данных класса TQuery, генерирует HTML-таблицу на основании данных, которые были извлечены последним из БД.

Рассмотрим пример. На основании SQL-запроса сгенерируем и отправим клиенту таблицу из базы данных shop.

Создайте новый проект и сохраните его под именем Webtable в каталоге cgi-bin Web-сервера, либо в любом другом месте жесткого диска, но после этого установите каталог cgi-bin Web-сервера в качестве выходного для создаваемых ЕХЕ-файлов (Output Directory).

Добавьте новое действие и установите его вызов по умолчанию. Теперь необходимо добавить В Web-МОДуЛЬ два компонента:

TQuery

И

TQueryTableProducer.

Установите следующие значения свойств компонента TQuery:

  • Name: Query;
  • DatabaseName: shop;
  • SQL: SELECT * from Products;
  • Active: True.

Значения свойств необходимо устанавливать именно в такой последовательности: сначала определяем БД, с которой будем работать, затем строку SQL-запроса. И именно в результате выполнения этой команды формируется таблица, с которой будет вестись работа. После этого можно открывать запрос к БД.

Выполнение команды SELECT в описанном виде приведет в выборке всех записей и полей, содержащихся в таблице. Подробное описание этой функции приведено в гл. 3.

Следует отметить, что после определения свойства SQL имеется возможность для выполнения запроса уже в режиме проектирования приложения. Для этого нужно лишь установить значение параметра Active в True.

Теперь можно заняться настройкой отображения таблицы. Присоединим компонент TQueryTableProducer к объекту Query. Для этого нужно прописать имя последнего в свойстве Query генератора таблиц. Далее в навигаторе объектов нашего Web-модуля появятся названия полей таблицы Products (в Delphi 5.0). Щелкая мышью по названиям полей, можно в окне Object Inspector их активизировать и, соответственно, получать доступ к их свойствам. Кроме того, существует возможность для визуального наблюдения за отображением столбцов и строк таблицы на Web-страниие. Для этого нужно лишь щелкнуть мышью по свойству columns в Object Inspector, когда текущим Объектом является Используемый Экземпляр класса TQueryTableProducer.

В этом редакторе можно устанавливать варианты отображения таблицы, наблюдая за результатом изменения настроек в нижней части редактора.

Рис. 10.12. Вид меню редактирования столбцов таблицы

Для определения свойств отображения конкретного столбца надо активизировать его в меню редактирования столбцов таблицы и, затем, обратиться к окну Object Inspector, где и станут доступны нужные параметры (рис. 10.12).

Здесь можно назначить цвет заднего плана, как для всего столбца, так и для его заголовка, поменять название столбца, отображаемое в таблице, и т. д.

Код, который генерирует этот компонент по умолчанию, содержит только таблицу, начинающуюся с тега <TABLE> и заканчивающуюся </TABLE>. Этот код можно вставлять в Web-страницу, посылаемую клиенту. Доступ к сгенерированному HTML-коду, являющемуся фрагментом документа, осуществляется путем вызова функции TqueryTabieProducer. Content, где название класса должно быть заменено именем соответствующего ему экземпляра. Однако генератор таблиц можно использовать и для получения всего HTML-документа. Для этого необходимо ввести коды, которые должны предшествовать таблице в документе, в свойство HEADER и последующие за ней — в FOOTER. Так мы и поступим в нашем примере. Добавим в свойство HEADER код, приведенный в листинге 10.9.

Листинг 10.9. Начало Web-страницы

<HTML>

<МЕТА http-equiv="Content-Type" content="text/html; charset=windows-1251">

<TITLE> Страница,; содержащая таблицу, полученную в результате выполнения

.SQL-запроса </TITLE> <Р>Сама таблица:

А в свойство FOOTER соответственно:

</HTML>

Теперь осталось лишь добавить новое действие, определить его вызов по умолчанию, в свойстве Producer записать название используемого объекта класса TQueryTabieProducer и запустить в браузере предварительно скомпилированный проект. Результат проведенной работы можно пронаблюдать на рис. 10.13.

Рис. 10.13. Динамически сформированная Web-страница

 

Программная реализация информационной системы на базе Web-технологий

В гл. 5была спроектирована ИС фирмы, осуществляющей продажи строительных материалов посредством Интернет-магазина. Наступило время проработать конечные структуру и взаимодействие объектов системы между собой, а также с источниками данных и создать несколько составляющих этого проекта.

 

Анализ и построение интерфейсов объектов

На диаграмме классов был представлен ряд объектов, из которых можно выделить группу, обеспечивающую непосредственно навигацию по магазину, разбор клиентского запроса, а также генерацию Web-страниц на базе представления, сформированного другими объектами.

Прежде всего, для ясного понимания функциональности работы системы необходимо четко отделить бизнес-логику от средств доступа к внешним данным в широком смысле этого слова. Это значит, что нужно на одни объекты возложить обязанности по приему данных от клиента и отсылке их ему, а на другие — обработку этих данных. Поскольку мы подошли к проекту с функциональной точки зрения (см. гл. 5),то и конечные обработчики запросов необходимо освободить от анализа внешних данных, возложив эту обязанность на некий промежуточный слой.

Вообще, жизненный цикл проектирования информационных систем включает в себя несколько стадий поступательного развития проекта, с возвращением назад для уточнения тех моментов, видение которых открывается разработчику только по мере приближения к финалу. Развитие происходит по спирали, когда создатель возвращается к уже проработанным этапам для их уточнения, а затем формирует проект на новом уровне детализации. Это позволяет, с одной стороны, избавляться от возникающих противоречий, а с другой — "двигаться не только вглубь, но и вширь", как сказали бы философы. Однако данная книга в большей степени посвящена технологиям реализации, а не проектирования, и поэтому мы примем к реализации именно тот проект, который был описан в гл. 5.

Итак, у нас есть диаграмма классов, представленная на рис. 5.4. С учетом знаний, изложенных в этой и предыдущих главах, ее элементам, а точнее классам, можно придать функциональный смысл. Справедливости ради, следует отметить, что авторы книги пользовались промежуточным вариантом проекта, но для четкости предоставляемых знаний мы показываем только конечный вариант проекта.

 

Класс, осуществляющий разбор сведений, содержащихся в запросе

Назовем этот класс TDispatcher. Очевидно, что нерационально самостоятельно программировать процесс получения данных запроса и затем модернизировать их представление в удобный к использованию вид. Пусть это делает стандартный для CGI-приложения объект Request. Работа TDispatcher начнется после получения запроса и вызова обработчика onAction единственного действия серверного модуля. Всю дальнейшую обработку сведений осуществят бизнес-объекты под управлением объекта класса TDispatcher.

Этот класс является наследником обычного Web-модуля (класса rwebModuie), и обладает некоторыми дополнительными методами

Нужно обеспечить выполнение как минимум двух процедур: извлечение всей интересующей информации и реализацию алгоритма работы системы с использованием других объектов. На основании этих требований опишем интерфейс класса TDispatcher (листинг 10.10).

Листинг 10.10 Интерфейс класса TDispatcher

TDispatcher = class(TWebModule)

procedure Action(Sender: TObject;

Request: TWebRequest; Response: TWebResponse; var Handled: Boolean)'; private

functionCreateCorrespondingView (position: String): TBasicView;

end;

В качестве параметра процедуры CreateCorrespondingView выступает строка, которая является частью GET-запроса и передается вместе с информацией о получении Web-страницы. В результате работы данного метода, один из объектов из набора TCategoriesView, TDetailsView, TPositionView, TCartView, TOrderView, TBiiiview будет создан и ссылка на него будет возвращена рассматриваемой функцией.

Класс TBillView, создаваемый для генерации счет- фактуры, обеспечивает работу ActiveX-формы, технология реализации которой будет описана в гл. 12.В данной версии реализации системы мы опустим описание и внедрение этого класса.

Как вы уже, наверное, догадались, данные объекты генерируют представления соответствующих страниц. Так вот, в соответствии со строкой, которая указана в качестве параметра, и создается соответствующий объект.

Процедура Action является единственным действием по умолчанию (при повторении проекта нужно это действие соответствующим образом создать).

Она Использует Приватный метод данного класса CreateCorrespondingView для вызова соответствующего объекта и передачи ему данных запроса. Кроме данных запроса, объекту — генератору ответа будет передаваться ссылка на структуру (объект) Response для помещения в него ответа.

 

Классы, генерирующие содержимое основных информационных страниц

Поскольку в работе магазина участвует целый набор страниц, предоставляющих различную информацию, содержание которых получается примерно одинаковым способом, то имеет смысл выделить объект, выполняющий работу по генерации соответствующего представления Web-страниц, который назван TBasicview. В дальнейшем, данный класс будет унаследован потомками для корректировки способа генерации представления Web-страниц.

Прежде всего, данный класс должен обеспечивать генерацию ответа клиенту. Для этого будет служить метод ForwardRequest, а параметрами будут являться объекты TWebRequest и TWebResponse. При вызове данного метода объектом класса Dispatcher ему передается информация о запросе и объект для помещения в него содержимого ответа. После этого класс выполняет определенные действия над запросом с целью подготовки всех служебных данных, а затем вызывает свой метод createContent для генерации HTML-содержимого ответа. Удобно использовать метод замещения динамическим содержимым "прозрачные" теги. Для этого нами будет использоваться генератор страниц (класс TPageProducer), при использовании которого нужно подготовить соответствующие шаблоны и описать процедуру опнтмътад. С этой целью объекты класса TBasicview и содержат этот метод. Кроме того, для различных целей, которые могут появиться при реализации классов- наследников, добавим виртуальный абстрактный метод HandieRequest. Это сделано с целью сохранения функциональных обязянностей других методов данного класса в случае, когда для подготовки HTML-содержимого нужно провести дополнительные операции. Итак, интерфейс класса TBasicview приведен в листинге 10.11.

Листинг 10.11. Интерфейс класса TBasicview

TBasicview = class private

fileName: TFileName; protected

request: TWebRequest; response: TWebResponse; public

constructor Create (flName: TFileName); procedure ForwardRequest (req: TWebRequest;

resp: TWebResponse); procedure OnHTMLTag (Sender: TObject; Tag: TTag;

const TagString: String;TagParams: TStrings; var ReplaceText: String); procedure HandieRequest (); virtual; function CreateContent (const TagString: string): String;

virtual; abstract;

end;

Теперь нам осталось описать интерфейсы классов-наследников TBasicview.

За некоторым исключением их интерфейсы повторяют друг друга. Это видно в листинге 10.12.

Листинг 10.12. Интерфейсы классов, генерирующих представление различных разделов магазина

// Отображение категорий товаровTCategoriesView = class (TBasicView) public

function CreateContent (const TagString: string): String;

override;

end;

// Отображение позиций (конкретных товаров)TPositionView = class (TBasicView) public function CreateContent (const TagString: string): String;

override;

end;

// Отображение детальной информации о товареTDetailsView = class (TBasicView) public function CreateContent (const TagString: string): String;

override;

end;

// Отображение корзинки TCartView = class (TBasicView) private cartltems: TStrings; public procedure HandleRequest ();

override;

function CreateContent (const TagString: string): String;

override;

end;

// Отображение формы уточнения заказаTOrderView = class (TBasicView) public function CreateContent (const TagString: string): String;

override;

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

Разумеется, все классы можно описывать и реализовывать по-разному. Более того, в этой системе можно было и вовсе обойтись без объектно-ориентированного подхода, поскольку реализуемый фрагмент ИС достаточно прост. В таких способах реализации Web-систем выбор алгоритма работы ложится на действия, а формирование Web-страниц осуществляется посредством использования шаблонов и объектов класса TWebProducer. С другой стороны, при кажущейся простоте и универсальности этих решений остается открытым вопрос о взаимодействии бизнес-объектов системы с объектами, которые взаимодействуют с CGI. Всегда необходимо находить разумное сочетание, распределяя функции между двумя основными компонентами системы. Это делается, поскольку единожды реализованное приложение, как правило, с течением времени модернизируется, улучшается и поэтому всегда уже на этапе проектирования нужно об этом задумываться, делая проект максимально гибким, а код "прозрачным". В принципе, в нашем примере сделан крен в область использования бизнес-объектов, но это лишь один из примеров разделения полномочий между объектами бизнес-логики и взаимодействия с CGI. При дополнении системы новыми функциями соответствующие добавляемые компоненты должны органично вписаться в созданную систему.

 

Реализация фрагмента информационной системы

Реализуемый фрагмент ИС будет иметь визуальное представление в браузере в виде фреймов. Его вид представлен на рис. 10.14.

Это представление обеспечивается кодом фрейм-содержащей страницы, приведенном в листинге 10.13.

Листинг 10.13. Содержание начальной Web-страницы модуля;

<HTML>

<МЕТА http-equiv="Content-Type" content="text/html; charset=windows-1251"> <ТIТLЕ>Вход в магазин</ТIТLЕ> <FRAMESET rows="*,150"> <FRAMESET cols="250,*">

<FRAME src="http://localhost/cgi-bin/shop?position=leftframe" name="leftframe">

<FRAME src="http://localhost/cgi-bin/shop?position=rightframe" name="rightframe">

</FRAMESET>

<FRAME src="http://localhost/cgi-bin/shop?position=korz" name="korz"> </FRAMESET> </HTML>

Рис. 10.14. Вид рабочей области ИС

При получении запроса клиента автоматически создается объект класса TDispatcher, являющийся наследником класса TWebModuie, и естестестенно нужно определить действие, которое будет выполняться по происхождению этого события. Для этого, как обычно, необходимо зайти на вкладку Events (События) окна Object Inspector и, дважды щелкнув мышью по полю, в которое помещается название требуемой функции, вызвать шаблон для ввода кода функции. После этого переименуйте функцию в Action и приведите ее к виду, приведенному в листинге 10.14.

Листинг 10.14. Код обработчика действия

//---- Задача: обработать запрос и подготовить контент ---

procedure TDispatcher.Action(Sender: TObject;

Request: TWebRequest; Response: TWebResponse; var Handled: Boolean); var

view: TBasicView; begin

view:= CreateCorrespondingView

(request.QueryFields.Values['position']);

(Здесь произошло извлечение из запроса значения поля с названием position. Обратите внимание на то, каким образом указаны ссылки во фрейм-содержащей странице. Именно указанием параметра position определяется, какую страницу серверный модуль должен создавать. Функция CreateCorrespondingView определяет тип объекта — обработчика запроса, и возвращает его в переменную view.)

if view <> Nil then begin

view.ForwardRequest (request, response);

// Был вызван метод ForwardRequestс целью получения ответа в объект

// response, который и будет отправлен клиенту.

view.Destroy;

end

end;

Как видим, первым делом нужно определить, какой собственно объект должен создавать HTML-код. Перейдем к реализации этой процедуры, приведенной в листинге 10.15.

Листинг 10.15. Реализация процедуры CreateCorrespondingView

//- — — Задача: выбрать нужное отображение ---------

function TDispatcher.CreateCorrespondingView

(position: String): TBasicView; begin

if 'position = 'leftframe' then

result:= TCategoriesView.Create ('templates\\Categories.htm') else if position = 'rightframe' then

result:= TPositionView.Create ('templates\\Position.htm') else if position = 'details' then

result:= TDetailsView.Create ('templates\\Details.htm') else if position = 'korz' then

result:= TCartView.Create ('templates\\Cart.htm') else if position = 'order' then

result:= TOrderView.Create ('templates\\0rder.htm') else if position = 'bill' then

result:= TBillView.Create ('templates\\Bill.htm') else

result:= nil;

end;

Обратите внимание, что в качестве параметра данного метода выступает название области, которую должен сгенерировать объект класса-наследника от TBasicView, а уже при создании экземпляра последнего ему передается путь к файлу-шаблону, на базе которого и формируется отправляемый HTML-документ.

Теперь можно переходить к реализации самих классов, генерирующих Web-страницы, и сначала следует создать главный класс TBasicview, от которого с некоторой модификацией наследуются другие. Еще раз отметим, что объекты их TBasicview не будут сами генерировать Web-страницу, это сделают наследники. Роль же этого класса заключается в описании общих для всех наследников методов и свойств. Такой подход позволит при необходимости легко модифицировать систему, корректируя лишь существующего наследника или добавляя новый. Реализация класса TBasicview приведена в листинге 10.16.

Листинг 10.16. Реализация класса TBasicview

constructor TBasicView.Create (flName: TFileName);

// Параметром конструктора является имя файла-шаблона Web-страницы,

// которое выбрал создатель данного объекта.begin

inherited Create; fileName:= flName;

// Здесь имя файла-шаблона было занесено в поле объекта.

end;

//—--- Общая процедура реакции на запрос -----------------

procedure TBasicView.ForwardRequest (req: TWebRequest;

resp: TWebResponse);

var

PageProducer: TPageProducer; begin

request:= req; response:= resp;

// ОбработкаHandleRequest ();

// Подготовка нового отображения на основе шаблонаPageProducer:= TPageProducer.Create(Nil); PageProducer.HTMLFile:= fileName; PageProducer.OnHtmlTag:= OnHtmlTag; resp.Content:= PageProducer.Content; PageProducer.Destroy;

end;

//----- Реакция на директиву подстановки ---------

procedure TBasicView.OnHTMLTag (Sender: TObject; Tag: TTag; const TagString: String; TagParams: TStrings; var ReplaceText: String);

begin

ReplaceText:= CreateContent (TagString);

end;

//----- Пустой обработчик запроса -------

{В случае необходимости дополнительной обработки, потомки могут переопределять эту процедуру.}

procedure TBasicView.HandleRequest ();

begin

end;

После реализации основного класса можно переходить к его наследникам, программный код которых приведен в листинге 10.17.

Листинг 10.17. Реализация потомков класса TBasicView

//----- Формирование отображения категорий товаров -------

function TCategoriesView.CreateContent (const TagString: string):. String;

var

query: TQuery;

begin

query:=tquery.create(Nil);

// Создан объект для организации запроса к базе данных.

query.DatabaseName:='shop';

// Указывается, какая база должна использоваться.

query.SQL.Add('SELECT DISTINCT КАТЕГОРИЯ FROM Products'); {Задана SQL-команда для выборки. Обратите внимание на параметр DISTINCT, означающий необходимость выборки только уникальных (неповторяющихся) записей из- поля КАТЕГОРИЯ }

query.open;

query.First;

// Запрос выполнен.

while not query.Eof do

{Здесь происходит перебор всех извлеченных записей с целью сформировать представление Web-страницы с категориями. Условием окончания перебора является достижение последней записи (EOF — End Of File)}

begin

result:= result + ('<LI><A href="http:\\localhost\cgi-bin\shop?' + 'position=rightframe&category=' + query.FieldValues['КАТЕГОРИЯ'] + '"target="rightframe">' + query.FieldValues['КАТЕГОРИЯ']+'</А>');

{В результате создается HTML-представление маркированного списка с названием категорий и соответствующими ссылками}

query.Next;

end;

query.Destroy;

end;

//----- Формирование отображения позиций (конкретных товаров) -----

function TPositionView.CreateContent (const TagString: string): String;

var

Integer; query: TQuery; categories: String;

begin

categories:= request.QueryFields.Values['category']; if categories = (' ') then

begin

{Здесь происходит обработка варианта, когда клиент только пришел в магазин и в качестве названия категории' ничего не указано)

result:='<Р> Добро пожаловать в магазин фирмы "Два кирпича".';

result:=result+'<>Выбирайте товары из категорий, представленных слева'

end

else

begin

result:=('<НЗ>Вы находитесь в категории </НЗ><Н4>'+categories+'</Н4>');

{Был помещен заголовок списка товаров, присутствующих в выбранной категории}

result: =Result+ (<ТАBLE><TR><TD>Название товара<ТО>Единица изме-рения<ТО>Цена за единицу');

query:=Tquery.Create(Nil); query.DatabaseName:='shop';

query.SQL.Add('SELECT IDJTOBAPA, МАРКА, Категория, ЕДИНИЦА_ИЗ, ЦЕНА_ЗА_ЕД FROM Products');

query.SQL.Add('WHERE Категория = "'+categories+ ""); query.open; query.First;

{Был осуществлен запрос к базе данных с указанием условия на выборку: поле "Категория" отбираемых записей должно содержать такое же слово, • какое содержится в переменной categories)

for i:=l to query.RecordCount do

begin

Result:=Result+

'<TR><TD>'+query.FieldValues['Марка']+

'<TD>'+query.FieldValues['Единица_из']+

'<TD>'+IntToStr(query.FieldValues['Цена_за_ед']) + (' руб.') -t-

'<TDXA href="http://localhost/cgi-bin/shop?'+

'position=details&ID='+

inttostr(query.FieldValues['ID'JTOBAPA'])+ '" target="new">nofipo6Hoe описание...</А>'+ '<TD>'+

'<A href="http://localhost/cgi-bin/shop?position=order&ID='+ inttostr(query.FieldValues['ID_TOBAPA'])+ 1">3аказать...</A>';

// Произойти описание строк таблицы.

query.Next;

end;

query.Destroy;

end;

end;

//----- Формирование отображения детальной информации о товаре----

function TDetailsView.CreateContent (const TagString: string): String;

var

query: TQuery; id: String;

begin

query:=Tquery.Create(Nil);

id:= request.QueryFields.Values['ID'];

query.DatabaseName:='shop';

query. SQL. Add ('SELECT * FROM Products WHERE ID_Товара = '"+id+"");

query.open;

if TagString = 'MARK' then

result:= query.FieldValues['МАРКА'] else if TagString = 'REPLACE' then

begin

if (query.FieldValues['ФОТОГРАФИЯ1] <> 'none') then

result:= '<IMG src='+query.FieldValues['ФОТОГРАФИЯ']+

' аlt="фотография">';

result:= result + '<Н4>Технические характеристики:</Н4>'+ '<H5>'+query.FieldValues['ТЕХНИЧЕСКИ']+'</H5>'+ '<H4Производитель</H4><H5>'+ query.FieldValues['ПРОИЗВОДИТ']+'</H5>'+ '<Н4>Единица измерения</Н4ХН5>' + query.FieldValues['ЕДИНИЦА_ИЗ']+'</H5>'+ '<Н4>Цена</Н4><Н5>'+

inttostr(query.FieldValues['ЦЕНА_ЗА_ЕД'])+'</H5>'+ ' <Н4Жатегория</Н4ХН5>' +query. FieldValues [' КАТЕГОРИЯ' ] + '</H5>'+ '<H4 >Примечание</Н4 ><H5>' + query.FieldValues['ПРИМЕЧАНИЕ']+'</H5>'; end;

query.Destroy;

end;

//----- Обработка запроса ---------

procedure TCartView.HandleRequest (}; var

addingID: String;

addingValue: String;

begin

// На основе Cookies, формируем список товаров в корзинке

cartltems:= request.CookieFields;

// Если необходимо добавить новый товар

addingValue:= request.QueryFields.Values['addingvalue']; addingID:= request.QueryFields.Values['addingid']; if addingValue <> '' then

begin

if StrToInt(addingValue) > 0 then

begin

// Добавляем к списку товаров в корзинкеcartltems.Add (addingid+'='+addingValue);

// А так же, сохраняем добавленный товар в Cookieswith response.Cookies.Add do

begin

Name:= addingID; Value:= addingValue;

end;

end;

end;

end;

//----- Формирование отображения карзинки-----------

function TCartView.CreateContent (const TagString: string): String;

var

query: TQuery; itemID: String;

i, price, sumCost, amount: Integer;

begin

if cartltems.Count = 0 then

result:=result+ ('<TR><TD> соlspan=Корзина пока пуста</ТАВLЕ>')

else

begin

query:= TQuery.create(Nil); query.DatabaseName: ='shop'; for i:=0 to (cartltems.Count-1) do

begin

itemID:= cartltems.Names[i];

amount:= StrToInt (cartltems.Values[itemID]);

query.sql.Clear;

query.SQL.add('SELECT * FROM Products WHERE ID_TOBAPA = ' +

itemID); query.Open;

query.First;

price:= query.FieldValues['ЦЕНА_ЗА_ЕД'];

result:=r.esult + '<TR><T'D>'+query. FieldValues ['МАРКА'] +

'<TD>'+IntToStr(amount) + '<TD>' +IntToStr(price) + '<TD>' +

IntToStr(price * amount); sumCost:=sumCost + price * amount; query.close; end; result:=result+'</TABLE>06iuaH стоимость: '+IntToStr(sumCost) +

1руб.'; query.Destroy;

end;

end;

//---- Формирование отображения формы уточнения заказа ----

function TOrderView.CreateContent (const TagString: string): String;

var

query: TQuery; id: String/begin

id:= request.QueryFields.Values['ID']; if TagString = 'MARK' then

begin

query:=Tquery.Create(Nil);

query.DatabaseName:='shop';

query.SQL.Add('SELECT * FROM Products WHERE 10_Товара = "'+

id+"");

query.open;

result:=query.FieldValues['МАРКА']; query.Destroy; end else if TagString = 'ID' then

result:= id;

end;

В заключение описания реализационной части приведем код шаблонов, совместно с которыми работают рассмотренные классы. Класс TCartview, создающий представление корзины, обращается к шаблону cart.htm, исходный текст которого представлен в листинге 10.18.

 

Листинг 10.18. Шаблон cart.htm

<HTML>

<BODY>

Позиции заказа:<BR> <TABLE border=l> <TR><TH width="50%">Hаименование товара

<TH width="15%">Kоличество

<TH width="15%">Ценa, рублей

<TH width="20%">Стоимость

<#REPLACE>

<ВН>Чтобы подтвердить покупку, нажмите

<А href='.'http: //localhost/cgi-bin/shop?position=bill"

target="_PARENT">Здесь</A>

</BODY>

</HTML>

При формировании содержимого правого фрейма классом icategoriesview используется шаблон categories.htm, код которого приведен в листинге 10.19.

Листинг 10.19. Шаблон categories.htm

<HTML>

<BODY>

<Р>Сегодня Интернет-магазин располагает следующими категориями товаров<ВЕ> <UL>

<#REPLACE>

</UL>

<Р>Для перехода к'интересующему разделу, щелкните по ссылке.

</BODY>

</HTML>

Подробное описание товаров создается классом TDetailsview с использованием шаблона, представленного в листинге 10.20.

Листинг 10.20. Шаблон Details.htm

<HTML>

<ТIТLЕ>Описание <#MARK> - магазин "Два кирпича" </TITLE>.

<BODY> <Hlx#MARKx/Hl>

<#REPLACE>

</BODY>

</HTML>

Добавление нового товара в корзину покупателя осуществляется посредством анкеты, которая создается объектом класса TOrderview, использующего шаблон, представленный в листинге 10.21.

Листинг 10.21. Шаблон Order.htm:

<HTML>

<BODY>

<hЗ>Помещение товара в корзину покупателя.</hЗ>

<р>Вы выбрали ' <#MARK> '

</р>

Укажите заказываемое количество единиц товара:

<form name="adding" method="GET" action="http://localhost/cgi-bin/shop"

target="korz">

<input type=hidden name="position" value="korz">

<input type=hidden name="addingid" value="<#ID>">

<input type="text" name="addingvalue" size="5"> ед. товара <br><br>

<input type="submit" уа!ие="Поместить в корзину" name="Submit"

onClick="window.history.back(2)">

</form>

</BODY>

</HTML>

В момент посещения клиентом начальной страницы магазина, HTML-код правого фрейма будет генерироваться на основании шаблона Position.htm, представленного в листинге 10.22.

Листинг 10.22. Шаблон Position.htm

<HTML>

<BODY>

<#REPLACE>

</BODY>

</HTML>

 

Демонстрация работы серверного модуля

Для демонстрации работы модуля установите его на ваш компьютер, переписав содержимое каталога source\chapterl0\ дискеты с примерами в каталог cgi-bin Web-сервера. Файл shop.htm необходимо скопировать отдельно в каталог для Web-страниц (в Apache это htdocs). После этого откройте файл shop.dpr в Delphi и откомпилируйте проект в запускаемый файл (меню Project | Build). Если вы не подключили базу данных, как описано в разд. "Подключение базы данных" настоящей главы, то сделайте это.

Данная реализация системы еще не завершена. В последующих главах будет, изложен материал, касающийся подготовки счета на базе технологии ActiveX, а также сервера, осуществляющего сохранения данных о клиентах в базе данных.

Наберите в браузере адрес http://localhost/shop. В окне браузера откроется наш пример магазина. Поработайте с ним. Посмотрите содержимое Web-страниц и особенно — гиперссылок, которые формируются динамически и определяют дальнейшее поведение системы при переходе по ним.

ГЛАВА 11




Поделиться с друзьями:


Дата добавления: 2014-12-29; Просмотров: 402; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.229 сек.