[{"id":"1","category":"categ_0","dateof":"2007.1.25","title":"title_0","comment":"hello}, … ];
« Разработка веб-страниц с помощью google gears. Часть 2 | Про java swing - часть 7 » |
Разработка веб-страниц с помощью google gears. Часть 3
Сегодня я продолжаю рассказ о google gears. В первой статье серии я рассказал о новой идее организации веб-приложений, легшей в основу технологии google gears. Тогда же в качестве примера я решил показать, как создать небольшое приложение “записная книжка”. Во второй статье мне пришлось сделать небольшое отступление от, собственно, gears и рассказать об sqlite (базе данных, где gears хранит пользовательскую информацию). Сегодня пришло время собрать эти кусочки воедино.С чего начинается разработка любого gears-приложения? Учитывая, что не у всех пользователей сети есть установленный в браузере плагин google gears, начать нужно с создания такого же по функциональности веб-приложения. Вот только, данные оно будет брать не из gears-хранилища, а из базы данных размещенной на веб-сервере. Gears должны не заменить привычные нам веб-приложения, а расширить их функциональность. Сайт должен работать всегда: даже, если у клиента нет поддержки gears. С другой стороны, мы понимаем, что необходимо заложить такой каркас приложения, чтобы при добавлении gears-функциональности нам не пришлось переделывать все с нуля. И тем более мы хотим избежать ситуации, когда возникнут две параллельные версии сайта (одна в стиле gears, другая в стиле classic). Акцент традиционного веб-приложения в том, что данные и внешний вид связаны - и это очень плохо. Ведь когда мы будем работать в режиме offline (без подключения к интернету), то данные должны браться не из Интернета, а из локального gears-хранилища. В первой статье, когда я говорил об архитектуре gears, то упомянул, что частью его функциональность является возможность сохранять во внутреннем КЭШе не только табличную информацию (за это отвечает sqlite), но элементы оформления (html, javascript, css). Значит, наше приложение будет размещено, по сути, в четырех местах: локальное и удаленное хранилище ресурсов (html, js, картинки), локальное и удаленно хранилище данных (sqlite). И если выбор источника ресурсов большей частью - задача gears, то выбор источника данных и загрузка информации из него лежит целиком на нас. Хочу сразу напугать: сделать хорошее gears-приложение без использования ajax-практически не возможно. Также, для работы с html (ведь страница будет динамически формироваться на стороне клиента) мне потребуется какая-нибудь хорошая javascript-библиотека. Естественно, я буду часто комментировать свои действия, но все же рекомендую найти и прочитать мою летнюю серию статей про ajax и jquery: именно эти инструменты нам сегодня понадобятся. Кроме того, методики веб-разработки, которые я сегодня покажу, могут быть применимы не только, когда вы пишите gears-приложение, но и при разработке (чуть не сказал традиционных) приложений асинхронно загружающих данные (ajax).
Этап 1: необходимо разработать html-страницу, содержащую каркас дизайна. Внешне записная книжка будет выглядеть так, как показано на рис 1.
В таблице будут перечислены заметки; а при “клике” по какой-либо из строк, внизу должна открываться форма редактирования текущей записи. Над таблицей расположен индикатор режима работы (offline или online), а также кнопка переключения между этими режимами. При переходе в режим offline данные с сервера будут загружаться в локальное хранилище, а при переходе в режим online данные следует закачать обратно на сервер.
Ниже приведен код создающий страницу-прототип.
<html>
<head>
<link rel="stylesheet" href="core.css" type="text/css" />
<script src="jquery.js"> </script>
</head>
<body>
<table id="header" border="1">
<tr>
<td id="hint_mode">Сообщаем какой режим активен</td>
<td id="hint_switch">Заготовка для кнопки переключения режимов</td>
</tr>
</table>
<table id="rows" border="1" cellspacing="0">
<tr>
<th>Категория</th>
<th>Дата</th>
<th>Заголовок</th>
</tr>
</table>
<table border="1" id="editor">
<tr>
<td>Категория:</td>
<td><input id="txt_category" /></td>
</tr>
<tr>
<td>Дата:</td>
<td><input id="txt_date" /></td>
</tr>
<tr>
<td>Заголовок:</td>
<td><input id="txt_title" /></td>
</tr>
<tr>
<td>Сообщение:</td>
<td><textarea id="txt_message" cols="30" rows="3"></textarea></td>
</tr>
</table>
</body>
</html>
Шаг 2: создать php-скрипт, выполняющий “установку” веб-приложения. Перед тем как мы начнем создавать код визуализирующий информацию из записной книжки, было бы неплохо создать саму эту записную книжку (базу данных, таблицу в ней, заполнить ее данными). Особой разницы между выбором, какую СУБД использовать на стороне веб-сервера нет. С равным успехом я мог использовать mysql, postgres, oracle. С другой стороны, раз мы в прошлый раз столько говорили об sqlite, то почему бы не использовать эту СУБД на обеих сторонах коммуникации? Предварительно проверьте, есть ли у вас на хостинге поддержка sqlite (в принципе, это стандарт, но для бесплатных и очень дешевых хостингов законы не писаны). Есть три набора функция для работы с sqlite: собственные функции расширения php_sqlite (их имена начинаются с префикса “sqlite_”), либо вы можете работать с этой базой посредством PDO или AdoDB. Естественно, что выбрать библиотеку для работы с sqlite не так просто, как кажется. Собственные функции расширения php_sqlite ориентированы на sqlite версии 2. А библиотека ADODB является “оберткой” над функциями php_sqlite и нам не поможет. Единственный способ для того, чтобы использовать средства sqlite3 (именно об этой версии я рассказывал в прошлой статье) и “обойтись малой кровью” - это воспользоваться PDO. PDO – унифицированный интерфейс работы с базами данных, который, как многие надеются, должен заменить собой все старые расширения и библиотеки в php. Далее я привожу код файла setup.php, его назначение создать sqlite базу данных, создать в ней таблицу и наполнить ее случайным набором данных (имитация заполненной записной книжки).
$conn = new PDO('sqlite:notebook.db3');
$conn->query ('DROP TABLE IF EXISTS notes');
$conn->query ('CREATE TABLE notes (id INTEGER PRIMARY KEY, category varchar(100),
dateof datetime, title varchar(100), comment TEXT) ');
$stmt = $conn->prepare("INSERT INTO notes (category, dateof, title, comment)
values (:category,:dateof,:title,:comment)");
$categs = array ('Покупки', 'Отдых', 'Работа', 'Семья');
for ($i = 0; $i < 50; $i++){
$stmt->bindValue(':category', iconv('windows-1251', 'utf-8',$categs[$i % 4]), PDO::PARAM_STR);
$stmt->bindValue(':dateof', '2007.'. (1+($i % 11)) . '.25', PDO::PARAM_STR);
$stmt->bindValue(':title', iconv('windows-1251', 'utf-8', 'Заметка_' . $i ), PDO::PARAM_STR);
$stmt->bindValue(':comment', iconv('windows-1251', 'utf-8', 'Информация_' . $i ), PDO::PARAM_STR);
$stmt->execute();
}
Шаг 3: создание php-скрипта, который отбирает данные из таблицы notes и возвращает этот список данных в виде … В виде чего? Нужно определить в каком из множества доступных форматов следует отправлять информацию клиенту. Традиционные приложения помещали информацию внутрь html-шаблона и отправляли клиенту готовый для “отрисовки” браузером html-документ. Нам этот способ не подойдет: визуализация должна быть проведена, именно, на стороне браузера, а не сервера (ведь приложение должно работать вне зависимости от того будут ли данные загружены с сервера или из локального хранилища). Когда я рассказывал об ajax, то говорил, что только два формата передачи данных являются общепринятыми стандартами: xml и json. Выбор одного из них кардинальным образом влияет и на то, как я буду писать код выполняющий сохранение загруженных с сервера данных в локальное хранилище gears. Влияет выбор и на то, как данные из хранилища будут отправляться на сервер для последующего сохранения. Нужно выбрать такой формат, который принесет наименьшее количество проблем. Предположим, что данные были загружены в формате xml, например, таком:
<note id="1">
<category ><![CDATA[categ_0]]></category >
<dateof><![CDATA[2007.1.25]]></dateof>
<title ><![CDATA[title_0]]></title >
<comment><![CDATA[Привет]]></comment>
</note>
Теперь проведем анализ дальнейшей обработки такого файла. Во-первых: xml-данные необходимо визуализировать, например, с помощью xslt-преобразования (здравствуй, еще сложная технология, которая, плюс к этому, не всегда корректно выполняются на распространенных браузерах). Либо выполнить “ручной” разбор xml-документа: с помощью множества циклов и условий мы можем “бегать” по дереву xml-документу, а найденные узлы помещать внутрь html-шаблона. И я не сказал бы, что это составит большие трудности. Несмотря на то, что “разбор” xml-я средствами DOM не всегда удобен, но ведь у нас в помощниках библиотека jquery. А с ней все становится проще. В первой статье про jquery я уделил внимание вопросу поиска элементов html-страницы с помощью xpath-нотации. Подобная функциональность применима и для xml-документов (как же иначе, ведь html – частный случай xml). Предположим, что в переменной msg находится ссылка на загруженный с сервера xml-документ. Тогда с помощью следующей строки кода я могу извлечь из входного документа массив (notes), содержащий все узлы “note”.
var notes = $('note',msg);
for (var i = 0; i < notes.length; i++){
var n = notes [i];
var id = $(n).attr('id');
var category = $('category', n)[0].firstChild.nodeValue;
//.. анализ остальных узлов
Так что, раз разбор xml-я так прост, значит именно этот формат мы выберем для обмена данными с сервером? Не торопитесь: ведь без анализа остались еще несколько этапов работы gears-приложения: сохранение информации внутрь gears таблицы, восстановление информации оттуда и отправка xml-на веб-сервер с последующим там его анализом. Я не буду приводить здесь детальные выкладки или прототипы кода для каждого из этих этапов (хотя сам сделал две версии записной книжки с целью оценить их трудоемкость и качество получающегося продукта). Но выводы озвучу: слишком много лишних действий, и слишком медленно все работает. Лишние действия связаны с тем, что в xml-е все сделано с избыточным запасом, так чтобы иметь возможность для хранения сложных иерархических структур данных (разве, записная книжка с 4-мя полями это сложная иерархическая структура?). Каждое из описанных выше трех действия требует значительны затрат времени (конечно, для небольшой книжки с десятком записей это не важно, но по мере роста приложения трудности будут множиться как снежный ком). Тут я немного лукавлю: фактически можно было бы сохранить весь xml-документ в одном единственном огромном текстовом поле одной единственной записи в базе данных. Но от затрат на построение DOM-дерева и его анализ мы бы все равно не смогли избежать, плюс это привело бы разрастанию количества javascript-кода. Да и вообще, эта методика пахнет каким-то иезуитством. Как вывод: xml использовать можно, но не нужно – используем JSON. JSON – сокращение от Javascript Object Notation. Проще говоря, это такой формат записи структур данных на javascript, который удобочитаем, компактен и, что самое главное, поддержка этого формата есть и на стороне браузера (не зря ведь в названии слово Javascript) и на стороне веб-сервера (PHP). Загружаемые с сервера данные будут выглядеть так:
header ('Content-Type: text/javascript');
$conn = new PDO('sqlite:notebook.db3');
$notes = array ();
foreach ($conn->query('SELECT * from notes') as $row) {
$notes [] = array ('id' => $row['id'],
'category' => $row['category'],
'dateof' => $row['dateof'],
'title' => $row['title'],
'comment' => $row['comment']);
}
print json_encode ($notes);
Обратите внимание на следующие моменты. Во-первых: я явно указал тип возвращаемой информации из скрипта как “text/javascript”, заменив тем самым значение по-умолчанию (“text/html”). Во-вторых: требуется, чтобы данные, которые подлежат json-кодированию, были в формате utf-8. Вспомните, когда я создавал скрипт заполняющий БД тестовыми записями, то акцентировал на этом внимание.
В следующий раз я продолжу рассказ об gears и нам предстоит организовать анализ загруженной с сервера информации, и динамически сформировать html-документ. Также нам пора разобраться в том, как сохранить эти записи в локальном sqlite хранилище.
« Разработка веб-страниц с помощью google gears. Часть 2 | Про java swing - часть 7 » |