Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax_v_deystvii.pdf
Скачиваний:
34
Добавлен:
05.03.2016
Размер:
5.83 Mб
Скачать

126 Часть I. Новый взгляд на Web-приложение

Рис. З.7. Отношение "многие ко многим", реализованное в базе данных.

Втаблице C o l o r s перечислены значения цвета для всех изделий,

врезультате исчезает необходимость хранить информацию о цвете

втаблице Garments

В-третьих, для генерации XML-данных непосредственно используется набор результатов, полученный после обработки запроса к базе. На первый взгляд, кажется, что такое решение обеспечивает высокую эффективность работы, но при этом возможны две проблемы. Соединение с базой остается открытым в течение всего времени генерации XML-данных. В данном случае в цикле while не производятся сложные расчеты и соединение не будет открыто слишком долго, но в общем случае такое решение может стать причиной напрасного расходования ресурсов. Кроме того, подобный подход применим, только если мы рассматриваем базу данных как "плоскую" структуру.

3.4.2. Реструктуризация модели

На данном этапе работы мы храним списки цвета и размеров чрезвычайно неэффективно — помещаем значения, разделенные запятыми, в поля таблицы Garments. Чтобы преобразовать данные в соответствии с реляционной моделью, мы должны создать отдельную таблицу для хранения всех доступных значений цвета и вспомогательную таблицу, которая связывала бы изделия с цветом. Подобное отношение называется "многие ко многим" и показано на рис. 3.7.

Предположим, например, что вам нужна охотничья шляпа и вы хотите выяснить, шляпы каких цветов есть в наличии. Для этого вы обращаетесь к ключу garment_id в таблице Garments_to_Colors. Эти записи дают возможность получить первичные ключи в таблице Colors, и по ним мы видим, что в наличии имеются охотничьи шляпы цвета shocking pink и blueberry, а шляп цвета battleship gray нет в наличии. Можно сформировать и обратный запрос и использовать таблицу Garments_to_Colors, чтобы выяснить, какие изделия имеют требуемый цвет.

Глава 3. Управление кодом Ajax

127

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

Инструмент Object-Relational Mapping

Существуют средства, способные выполнить описанную задачу за нас. Для этой цели подходит набор инструментов ORM (Object-Relational Mapping), которые автоматически преобразуют данные, содержащиеся в базе, в объект, хранящийся в памяти компьютера. При этом разработчик избавлен от необходимости формировать низкоуровневые SQL-выражения. Программисты, использующие РНР, могут обратиться к PEAR DB_DataObject, EZPDO (Easy PHP Data Objects) или Metastorage. Разработчики, применяющие Java, ограничены в выборе. Им доступен лишь продукт Hibernate (теперь он перенесен и на платформу .NET). Инструменты ORM — обширная тема, рассматривать которую мы сейчас не будем.

Рассматривая наше приложение с точки зрения MVC, легко увидеть, что применение ORM дает интересный побочный эффект — с самого начала у нас в руках оказываются основы модели. Мы можем написать программу генерации XML-данных, которая будет взаимодействовать с объектом Garment, предоставив ORM самостоятельно выполнять все необходимые действия с базой. Мы больше не привязаны к API конкретной базы данных и не должны учитывать особенности ее работы. В листинге 3.7 показаны изменения кода, связанные с переходом к ORM.

В данном случае мы определяем бизнес-объекты (т.е. модель) на РНР, используя Pear: :DB_DataObject, в результате чего наши классы становятся расширением базового класса DB_DataObject. Различные ORM делают это по-разному, но в результате мы получаем набор объектов, к которым можем обращаться как к обычному коду, абстрагируясь от сложных SQL-выражений.

Листинг 3.7. Объектная модель для приложения

require_once "DB/DataObject.php";

class GarmentColor extends DB_DataObject { var $id;

var $garment_id; var $color_id;

}

class Color extends DB_DataObject { var $id;

var $name;

}

class Garment extends DB_DataObject { var $id;

var $title;

var $description; var $price;

var $colors;

128 Часть I. Новый взглядна Web-приложение

var $category; function getColors(){

if (!isset($this->colors)){ $linkObject=new GarmentColor(); $linkObject->garment_id = $this->id; $linkObject->find(); $colors=array();

while ($linkObject->fetch()){ $colorObject=new Color(),• $colorObject->id=$linkObject->color_id; $colorObject->find();

while ($colorObj ect->fetch()){ $colors[] = clone($colorObject);

}

}

}

return $colors;

}

}

Помимо основного объекта Garment, мы определяем объект Color и метод объекта Garment, предназначенный для получения всех доступных цветов. Размеры поддерживаются аналогичным способом. Поскольку библиотека непосредственно не поддерживает отношение "многие ко многим", нам надо определить объект для связующей таблицы и организовать перебор в методе getColors (). Несмотря на это модель выглядит завершенной и удобна для восприятия. Рассмотрим, как можно применить данную модель к нашему документу.

Использование обновленной модели

Мы сгенерировали модель на основе более совершенной структуры базы данных. Теперь нам надо использовать ее в нашем PHP-сценарии. В листинге 3.8 показан код страницы, использующей объекты на базе ORM.

Листинг 3.8. Страница, использующая ORM для взаимодействия с базой

<?php

header("Content-type: application/xml");

echo "<?xml version=\"l.0\" encoding=\"UTF-8\" ?>\n"; include "gannent_busines8_objects.inc"

$garment=new Garment; $garment->category = $_GET["cat"]; $number_of_rows = $garment->find(); echo "<garments>\n";

while ( $garment->fetch()) { printf("<garment id=\"%s\" title=\"%s\">\n"

. "<description>%s</descrJ^tion>\n<price>%s</price>\n", $garment->id,

$garment->title, $garment->description, $garment->price

);

Scolors»

Глава 3. Управление кодом Ajax 129

$garment->getColors(); if (count($colors)>0){ echo "<colors>\n";

for($i=0; $i<count($colors);$i++){ echo "<color>{$colors[$i]}</color>\n";

}

echo "</colors>\n";

}

echo "</garment>\n";

}

echo "</garments>\n"; ?>

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

3.4.3. Разделение содержимого и представления

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

Системы на базе шаблонов

Для решения данной задачи используется язык шаблонов. Система, поддерживающая шаблоны, получает текстовый документ, содержащий специальную разметку. Элементы разметки обозначают позиции реальных переменных. К языкам шаблонов можно отнести PHP, ASP и JSP, которые позволяют включать фрагменты кода в содержимое Web-страниц. Этим они принципиально отличаются от кодов, включающих содержимое, примерами которых являются Java-сервлеты или традиционные сценарии CGI. Несмотря на то что сценарии предоставляют достаточно мощные средства обработки запросов, используя их, очень трудно разделить бизнес-логику и представление.

Языки сценариев, ориентированные на конкретное применение, например PHP Smarty и Apache Velocity (система на базе Java; при переносе на платформу .NET она получила название N Velocity), предоставляют ограниченные возможности для создания кода. В ряде случаев поток управления

130 Часть I. Новый взгляд на Web-приложение

может содержать лишь ветвление (оператор if) и циклы (например, операто-

 

ры for и while). В листинге 3.9 показан шаблон PHP Smarty для генерации

I

XML-данных.

 

<?xml version="1.0" encoding="UTF-8" ?>

 

<garments>

 

{section name=garment loop=$garments}

 

<garment id="{$garment.id}" title="{$garment.title}">

 

<description>{$garment.description}</description>

 

<price>{$garment.price}</price>

 

(if count($garment.getColors())>0}

 

<colors>

 

{section name=color loop=$garment.getColors()}

 

<color>$color->name</color>

 

{/section}

 

</colors>

 

{/if}

 

</garment>

 

{/section}

 

</garments>

_

Входной информацией для шаблона является переменная массива gar-

 

ments, содержащего объекты Garment. Блыпая часть шаблона генерируется

 

процессором, а разделы в фигурных скобках интерпретируются как инструк-

 

ции. Они либо заменяются именами переменных, либо интерпретируются как

 

выражения ветвления и циклов. Структура выходного XML-документа, вы-

 

раженная в виде шаблона, воспринимается гораздо лучше, чем код, подобный

 

тому, который был представлен в листинге 3.7. Теперь поговорим о том, как

 

применить шаблон к нашему документу.

 

Использование обновленного представления

Мы переместили определение XML-данных из основного документа в шаблон Smarty. В результате главная страница должна лишь установить процессор шаблона и передать необходимые данные. В листинге 3.10 отражены изменения, необходимые для этого.

Листинг 3.10. Использование Smarty для генерации XML-данных

<?php

header("Content-type: application/xml"); include "garment_business_objects.inc"; include "smarty.class.php";

$garment«new DataObjects_Garment; $garment->category = $_GET["cat"] ; $number_of_rows - $garment->find(); $smarty-new Smarty;

$3marty->assign('garments', $garments); $smarty->display('garments_xml.tpl'); ?>

Глава 3. Управление кодом Ajax 131

рис. 3.8. Архитектура MVC применима к Web-приложениям. Web-страница или сервлет действует как контроллер и обращается к модели для получения

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

Обычно действия с шаблонами насчитывают три этапа. Сначала мы создаем шаблон Smarty, затем заполняем его переменными. В данном случае переменная только одна, но мы можем использовать их столько, сколько нам надо. Например, если информация о пользователе хранится вместе с данными о сеансе, мы можем сформировать посредством шаблона персональное приветствие. После этого мы вызываем функцию display () и передаем ей имя файла шаблона.

Итак, нам удалось отделить представление от страницы с результатами поиска. Формат XML определяется только один раз, и мы можем организовать воспроизведение данных несколькими строками кода. Страница с результатами поиска теперь ориентирована на решение одной задачи и содержит только необходимую для этого информацию, а именно: параметры поиска и определение выходного формата. Если вы помните, мы хотели обеспечить возможность легко переходить к форматам, альтернативным XML. С помощью Smarty это достигается просто, мы лишь определяем дополнительный формат. Если мы хотим реализовать структуру, обеспечивающую минимум изменений, мы можем даже использовать шаблон внутри другого шаблона.

Если вы вспомните, в чем состоит архитектура "модель-представление- контроллер", то увидите, что наше приложение соответствует ей. Реализация приложения условно показана на рис. 3.8.

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

Мы рассмотрели пример применения архитектуры "модель-представление- контроллер" к Web-приложению. Мы обсуждали серверные программы приложения Ajax, поддерживающего XML-документы, но нетрудно понять, как применить данную архитектуру к классическому Web-приложению, поддерживающему HTML-документы.

В зависимости от технологий, возможны вариации данного образа разработки, но общие принципы остаются теми же. Компоненты Enterprise Jav-

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]