2 Авг
Среди форматов обмена данными, AJAX программисты часто выделяют JSON (JavaScript Object Notation, “джейсн”), как альтернатива языку XML, а именно потому, что XML больше язык разметки, чем носитель данных. JSON в свою очередь, легкий, человеко-читабельный, текстовый формат для хранения и передачи простых структурированных данных, а так же более комплексных объектов (массивов). В этом уроке мы рассмотрим простой пример формирования данных в JSON средствами PHP, а так же их получение и представление, с помощью JavaScript. Кто еще не понял, это продолжение серии уроков “AJAX PHP поиск” (XML, Prototype).
Чем отличается представление данных в JSON от, допустим, XML. Простой пример:
{ "players" : [
{ "firstName" : "Ryan", "lastName" : "Campbell", "position" : "S" },
{ "firstName" : "Chris", "lastName" : "Campbell", "position" : "QB" },
{ "firstName" : "Kevin", "lastName" : "Hale", "position" : "DT" }
]}Здесь у нас есть элемент players, который в свою очередь является массивом из трех “рядов”, а каждый такой “ряд” это массив еще из трех элементов (firstName, lastName, position). Самое интересное то, что в языке JavaScript есть встроенная функция eval(), которая “парсит” (разбирает) такие строки.
Ну например, допустим у нас эти данные хранятся в переменной s (уже в JavaScript):
var obj = eval("(" + s + ")");
Мы получаем объект obj, который будет хранить все эти данные в очень удобной структуре:
alert(obj.players[0].firstName); // Ryan alert(obj.players[1].lastName); // Campbell alert(obj.players[2].position); // DT
Вот таким образом мы получаем доступ к JSON данным. Формирование таких данных мало чем отличается. Ну например на языке PHP:
1 2 3 4 5 6 7 8 9 10 | $a = array(); $a["players"][0]["firstName"] = "Ryan"; $a["players"][0]["lastName"] = "Campbell"; $a["players"][0]["position"] = "S"; ... $json = new Services_JSON(); echo $json->encode($a); |
На входе методу encode() подается любой массив, и метод возвращает закодированный в JSON такой же массив, готовый для передачи куда-либо.
Вспомним уроки создания AJAX поиска методами XML и Prototype. Попробуем еще разок продублировать этот пример, только уже с использованием JSON для представления данных.
Посмотреть в действии можно здесь:
http://logicerror.pp.ru/upload/ajax_search_json/
Начинаем:
В php5 уже встроены функции для работы с JSON данными. Для php4 качаем PEAR библиотеку json.php отсюда:
http://pear.php.net/pepr/pepr-proposal-show.php?id=198
База данных и HTML представление страницы у нас не изменилось совсем (ну кроме заголовка в HTML), так что у кого до сих пор нет, копируем отсюда:
http://blog.kovshenin.com/archives/ajax-php-search-xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | function getXmlHttp() { var xmlhttp; try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } } if (!xmlhttp && typeof XMLHttpRequest != 'undefined') { xmlhttp = new XMLHttpRequest(); } return xmlhttp; } function search() { var sSearch = document.getElementById("search_input").value; if (sSearch.length < 3) { alert("Запрос должен быть не короче 3-х символов."); return false; } var xmlHttp; xmlHttp = getXmlHttp(); var obj = document.getElementById("search_results"); obj.innerHTML = ""; var loading = document.getElementById("searching"); loading.style.display = "block"; xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4) { loading.style.display = "none"; var json = eval( "(" + xmlHttp.responseText + ")" ); for (var i = 0; i < json.entry.length; i++) { var new_el = document.createElement("div"); new_el.innerHTML = "<h1>" + json.entry[i].title + "</h1>" + json.entry[i].content; new_el.className = "result"; obj.appendChild(new_el); } } } xmlHttp.open('GET', 'search.php?search='+sSearch+'&rand='+Math.random(), true); xmlHttp.send(null); } |
В script.js у нас произошли некоторые изменения в районе обработки и представления данных. Рассмотрим по порядку:
var json = eval( "(" + xmlHttp.responseText + ")" );
В переменную json, мы помещаем объект полученный функцией eval, которая целиком разбирает текст полученный с запрашиваемой страницы - xmlHttp.responseText (JSON ведь именно в текстовом формате данные хранит, помните?). Таким образом, переменная json у нас теперь полноценный объект с данными результата поиска.
1 2 3 4 5 6 7 8 | for (var i = 0; i < json.entry.length; i++) { var new_el = document.createElement("div"); new_el.innerHTML = "<h1>" + json.entry[i].title + "</h1>" + json.entry[i].content; new_el.className = "result"; obj.appendChild(new_el); } |
Здесь, узнав сколько всего записей у нас получено (json.entry.length, где entry у нас массив - поймете когда дойдем до части php), мы в цикле обрабатываем все элементы этих записей. То есть, как и в первом самом уроке, создаем новый элемент div, помещаем в него (.innerHTML) один сформированный результат поиска, присваиваем класс result, ну и наконец приклеиваем к объекту obj (поле для результатов поиска).
Теперь рассмотрим, как мы сформировали JSON данные.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <?php $db = mysql_connect("localhost", "root", ""); mysql_select_db("ajax_search"); mysql_query("SET CHARACTER SET utf8"); require("json.php"); header('Content-type: application/json; charset=utf-8'); header('Cache-Control: no-cache'); $entry = array(); $sString = mysql_real_escape_string($_GET["search"], $db); $sql="SELECT * FROM `articles` WHERE `title` LIKE '%$sString%' OR `content` LIKE '%$sString%' ORDER BY `id` DESC LIMIT 10"; $rs=mysql_query($sql,$db); if (mysql_num_rows($rs) > 0) { $i = 0; while ($row = mysql_fetch_array($rs)) { $content=htmlspecialchars(strip_tags($row["content"])); if (mb_strlen($content, "utf-8") > 250) $content = mb_substr($content, 0, 250, "utf-8") . "..."; $entry["entry"][$i]["title"] = htmlspecialchars($row["title"]); $entry["entry"][$i]["content"] = $content; $i++; } } else { $entry["entry"][0]["title"] = ""; $entry["entry"][0]["content"] = "Ничего не найдено"; } $json = new Services_JSON(); echo $json->encode($entry); ?> |
Подключение к базе данных и составление запроса поиска, думаю хватит уже обсуждать. Перейдем сразу к делу:
require("json.php");
Мы работаем на php4, так что обязательно подключаем PEAR библиотеку JSON (в которой и описан класс Services_JSON и методы encode/decode.
header('Content-type: application/json; charset=utf-8');
Согласно RFC 4627 JSON данные должны иметь MIME тип application/json, учтите это.
$entry = array();
Создаем простой пустой массив $entry. Сюда мы будем записывать наши данные, а потом кодировать в формат JSON.
1 2 3 4 5 6 7 8 9 10 | $i = 0; while ($row = mysql_fetch_array($rs)) { $content=htmlspecialchars(strip_tags($row["content"])); if (mb_strlen($content, "utf-8") > 250) $content = mb_substr($content, 0, 250, "utf-8") . "..."; $entry["entry"][$i]["title"] = htmlspecialchars($row["title"]); $entry["entry"][$i]["content"] = $content; $i++; } |
Здесь переменная $i будет служить в качестве счетчика, далее обрабатываем поля title и content из базы данных (как и раньше), и в своеобразной форме записываем в массив $entry. Расскажу о структуре массива. Первый элемент у нас всегда будет “entry” - мы так к нему обращаемся в javascript - json.entry. Второй элемент - порядковый номер результата (счетчик наш), так же используется в js - json.entry[i]. Ну и последние элементы - поля title и content. И таким же образом к ним обращается js - json.entry[i].title и json.entry[i].content.
$entry["entry"][0]["title"] = ""; $entry["entry"][0]["content"] = "Ничего не найдено";
В случае если поисковой запрос не дал результатов, мы в массив $entry помещаем всего одну запись - нчиего не найдено.
$json = new Services_JSON(); echo $json->encode($entry);
Здесь все просто. Создаем новый объект из класса Services_JSON(), и вызываем функцию encode(), передав наш массив $entry в качестве параметра. Ну и естественно выводим это все.
Ну вот, собственно, и все.
По сравнению с XML, JSON более прост и удобен в использовании (особенно тем, кто хорошо ориентируется в массивах), но есть несколько нюансов по безопасности - обязательно проверяйте JSON данные на код javascript перед тем, как использовать его в eval(), т.к. эта функция исполняет javascript код.
Ну а с Prototype можно и не сравнивать, особенно если использовать их в паре - Prototype+JSON. Prototype для удобной работы с AJAX запросами, а JSON для удобного представления данных.
Оставьте отзыв