Система комментирования на Ajax
В данном уроке мы будем создавать простую систему комментирования на Ajax. Мы рассмотрим, как добиться эффективного взаимодействия между jQuery и связкой PHP/MySQL с помощью JSON.
Шаг 1 - XHTML
Сначала давайте взглянем на разметку комментариев. Этот код генерируется средствами PHP в классе Comment, который мы вскоре рассмотрим.
demo.php
<div class="comment"> <div class="avatar"> <a href="http://tutorialzine.com/"> <img src="http://www.gravatar.com/avatar/112fdf7a8fe3609e7af2cd3873b5c6bd?size=50&default=http%3A%2F%2Fdemo.tutorialzine.com%2F2010%2F06%2Fsimple-ajax-commenting-system%2Fimg%2Fdefault_avatar.gif"> </a> </div> <div class="name"><a href="http://tutorialzine.com/">Person's Name</a></div> <div title="Added at 06:40 on 30 Jun 2010" class="date">30 Jun 2010</div> <p>Comment Body</p> </div>
Блок с классом avatar содержит ссылку (если человек ввел при комментировании верный url) и картинку-аватар, которая забирается с сайта gravatar.com. Мы вернемся к этому моменту, когда будем разбирать PHP-код данного примера. Также у нас есть блоки с именами name и time, и тело комментария.
Другой важный момент в разметке - форма, данные из которой отправляются методом POST. Все поля, кроме адреса сайта, обязательны для заполнения.
demo.php
<div id="addCommentContainer"> <p>Add a Comment</p> <form id="addCommentForm" method="post" action=""> <div> <label for="name">Your Name</label> <input type="text" name="name" id="name" /> <label for="email">Your Email</label> <input type="text" name="email" id="email" /> <label for="url">Website (not required)</label> <input type="text" name="url" id="url" /> <label for="body">Comment Body</label> <textarea name="body" id="body" cols="20" rows="5"></textarea> <input type="submit" id="submit" value="Submit" /> </div> </form> </div>
Форма отправляется через Ajax. Валидация целиком происходит в файле submit.php, о чем мы поговорим в части про jQuery. Каждое поле имеет соответствующий элемент label с атрибутом for.

Шаг 2 – PHP
PHP взаимодействует с MySQL и генерирует разметку комментариев. Он также получает Ajax-запросы и вставляет данные комментариев в таблицу comments в базе. Ниже приведен код, который выводит комментарии на страницу.
demo.php
/* / получаем все комментарии и заполняем массив comments объектами */ $comments = array(); $result = mysql_query("SELECT * FROM comments ORDER BY id ASC"); while($row = mysql_fetch_assoc($result)) { $comments[] = new Comment($row); }
SQL-запрос забирает все записи из базы данных и заполняет массив comments объектами класса comments, о котором мы поговорим ниже. Данный массив потом выводится на экран.
demo.php
/* / выводим комментарии один за одним: */ foreach($comments as $c){ echo $c->markup(); }
Каждый комментарий содержит метод markup(), который генерирует готовую к использованию на странице HTML-разметку. Вы можете видеть объявление этого метода и класса ниже.
— Регулярная проверка качества ссылок по более чем 100 показателям и ежедневный пересчет показателей качества проекта.
— Все известные форматы ссылок: арендные ссылки, вечные ссылки, публикации (упоминания, мнения, отзывы, статьи, пресс-релизы).
— SeoHammer покажет, где рост или падение, а также запросы, на которые нужно обратить внимание.
SeoHammer еще предоставляет технологию Буст, она ускоряет продвижение в десятки раз, а первые результаты появляются уже в течение первых 7 дней. Зарегистрироваться и Начать продвижение
Класс забирает один ряд из базы (с помощью функции mysql_fetch_assoc()) и сохраняет его в переменную data со спецификатором private. Это делает ее доступной только для методов текущего класса. Обратиться к ней извне класса не удастся.
comment.class.php – Часть 1
class Comment { private $data = array(); public function __construct($row) { /* / Конструктор */ $this->data = $row; } public function markup() { /* / Данный метод занимается выводом разметки XHTML для комментария */ // Устанавливаем алиас, чтобы не писать каждый раз $this->data $d = &$this->data; $link_open = ''; $link_close = ''; if($d['url']){ // Если человек ввел url при добавлении комментария, // определяем открывающий и закрывающий тэги для ссылки $link_open = '<a href="'.$d['url'].'">'; $link_close = '</a>'; } // Конвертируем время в UNIX timestamp: $d['dt'] = strtotime($d['dt']); // Нужно для аватара по умолчанию: $url = 'http://'.dirname($_SERVER['SERVER_NAME'].$_SERVER["REQUEST_URI"]). '/img/default_avatar.gif'; return ' <div class="comment"> <div class="avatar"> '.$link_open.' <img src="http://www.gravatar.com/avatar/'. md5($d['email']).'?size=50&default='. urlencode($url).'" /> '.$link_close.' </div> <div class="name">'.$link_open.$d['name'].$link_close.'</div> <div class="date" title="Added at '. date('H:i \o\n d M Y',$d['dt']).'">'. date('d M Y',$d['dt']).'</div> <p>'.$d['body'].'</p> </div> '; }
Данный скрипт использует gravatar для вывода аватаров в комментариях. Для тех, кто еще не сталкивался с данным сервисом, он позволяет вам ассоциировать аватар с email-адресом. Аватар можно получить просто передав сервису gravatar.com md5() хэш от вашего e-mail адреса.
Также скрипт пытается выяснить url-адрес, по которому он расположен и определяет точный адрес картинки default_avatar.gif. Данный рисунок передается сервису вместе с хэшем, поэтому, если не было найдено аватара для конкретного email-адреса, то отображается резервная картинка.
comment.class.php – Часть 2
public static function validate(&$arr) { /* / Данный метод проводит валидацию данных, переданных через Ajax. / / возвращает true/false в зависимости от результата валидации, наполняет массив $arr / введенными данными (если они верны), либо сообщениями об ошибках. */ $errors = array(); $data = array(); // Используем функцию filter_input, введенную в PHP 5.2.0 if(!($data['email'] = filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL))) { $errors['email'] = 'Please enter a valid Email.'; } if(!($data['url'] = filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL))) { // Если в поле Url введен некорректный адрес, // то действуем так, будто он вовсе не был введен $url = ''; } // Использование фильтров с пользовательской функцией обратного вызова: if(!($data['body'] = filter_input(INPUT_POST,'body',FILTER_CALLBACK, array('options'=>'Comment::validate_text')))) { $errors['body'] = 'Please enter a comment body.'; } if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK, array('options'=>'Comment::validate_text')))) { $errors['name'] = 'Please enter a name.'; } if(!empty($errors)){ // Если есть ошибки, копируем массив $errors в $arr: $arr = $errors; return false; } // Если введенная информация корректна, очищаем ее и копируем в $arr: foreach($data as $k=>$v){ $arr[$k] = mysql_real_escape_string($v); } // Приводим email к нижнему регистру (для корректного хэша для gravatar): $arr['email'] = strtolower(trim($arr['email'])); return true; }
Метод validate() (он также - часть класса) объявлен как статический. Это означает, что он может быть вызван непосредственно с помощью Comment::validate() без необходимости создавать экземпляр объекта. Данный метод производит валидацию данных, переданных через Ajax.
Данный метод использует новые функции фильтрации, введенные в PHP 5.2.0. Они позволяют нам легко проверить введенную информацию, переданную обработчику. К примеру, filter_input(INPUT_POST,’url’,FILTER_VALIDATE_URL) означает, что мы проверяем, является ли $_POST['url'] корректным URL-адресом. Если да, функция вернет значение проверяемой переменной, в противном случае - ложь (false).
Это действительно удобно, так как еще недавно мы вынуждены были проверять подобные вещи, придумывая хитрые регулярные выражения и серии конструкций if.
Мы также имеем возможность использовать собственные функции для дополнительной обработки информации.
comment.class.php – Часть 3
private static function validate_text($str) { /* / Данный метод используется внутри как FILTER_CALLBACK */ if(mb_strlen($str,'utf8')<1) return false; // кодируем спецсимволы html (<, >, ", & .. etc) и конвертируем // переносы строк в тэги <br>: $str = nl2br(htmlspecialchars($str)); // Удаляем оставшиеся переносы строк $str = str_replace(array(chr(10),chr(13)),'',$str); return $str; } }
Последний метод - validate_text(), который мы передаем как callback-функцию в два вызова filter_input выше. Она кодирует все спецсимволы HTML, надежно защищая от XSS-атак. Также он заменяет переносы строк тэгами <br />.
submit.php
/* / Массив будет наполняться или переданной информацией, / или сообщениями об ошибках /*/ $arr = array(); $validates = Comment::validate($arr); if($validates) { /* все нормально, вставляем в базу: */ mysql_query(" INSERT INTO comments(name,url,email,body) VALUES ( '".$arr['name']."', '".$arr['url']."', '".$arr['email']."', '".$arr['body']."' )"); $arr['dt'] = date('r',time()); $arr['id'] = mysql_insert_id(); /* / Информация в массиве $arr экранируется перед проведением вставки, / но нам нужен неэкранированный текст, поэтому мы применяем / функцию stripslashes() ко всем элементам массива: /*/ $arr = array_map('stripslashes',$arr); $insertedComment = new Comment($arr); /* Вывод разметки только что введенного комментария: */ echo json_encode(array('status'=>1,'html'=>$insertedComment->markup())); } else { /* Вывод сообщений об ошибках */ echo '{"status":0,"errors":'.json_encode($arr).'}'; }
Файл submit.php получает информацию из формы комментирования через Ajax-запрос. Он проверяет данные и выводит объект JSON либо с HTML разметкой успешно добавленного комментария, либо со списком ошибок. jQuery использует свойство status для определения того, выводить ли сообщения об ошибках, либо разметку для комментария.
— Разгрузит мастера, специалиста или компанию;
— Позволит гибко управлять расписанием и загрузкой;
— Разошлет оповещения о новых услугах или акциях;
— Позволит принять оплату на карту/кошелек/счет;
— Позволит записываться на групповые и персональные посещения;
— Поможет получить от клиента отзывы о визите к вам;
— Включает в себя сервис чаевых.
Для новых пользователей первый месяц бесплатно. Зарегистрироваться в сервисе
Ниже вы можете видеть два гипотетических ответа:
Успешный ответ
{ "status": 1, "html": "Html Code Of The Comment Comes Here..." }
Неуспешный ответ
{ "status": 0, "errors": { "email": "Please enter a valid Email.", "body": "Please enter a comment body.", "name": "Please enter a name." } }
При неуспешном ответе, jQuery проходит циклом по объектам, содержащим ошибки и выводит текст ошибки рядом с соответствующим полем формы.

Шаг 3 – CSS
Теперь, когда вся разметка у нас корректно генерируется и отображается на странице, можно переходить к ее стилевому оформлению.
styles.css – Часть 1
.comment, #addCommentContainer{ /* Стили для комментариев и формы */ padding:12px; width:400px; position:relative; background-color:#fcfcfc; border:1px solid white; color:#888; margin-bottom:25px; /* CSS3 скругленные углы и тени */ -moz-border-radius:10px; -webkit-border-radius:10px; border-radius:10px; -moz-box-shadow:2px 2px 0 #c2c2c2; -webkit-box-shadow:2px 2px 0 #c2c2c2; box-shadow:2px 2px 0 #c2c2c2; } .comment .avatar{ /* / блок avatar спозиционирован абсолютно */ height:50px; left:-70px; position:absolute; width:50px; background:url('img/default_avatar.gif') no-repeat #fcfcfc; /* Центрируем по вертикали: */ margin-top:-25px; top:50%; -moz-box-shadow:1px 1px 0 #c2c2c2; -webkit-box-shadow:1px 1px 0 #c2c2c2; box-shadow:1px 1px 0 #c2c2c2; }
Применяется ряд стилей из CSS3, включая скругленные углы и тени. Ясно, что в старых браузерах это работать не будет. Однако - это всего лишь представление, которое не влияет на функционирование самого скрипта.
styles.css – Часть 2
.comment .avatar img{ display:block; } .comment .name{ font-size:20px; padding-bottom:10px; color:#ccc; } .comment .date{ font-size:10px; padding:6px 0; position:absolute; right:15px; top:10px; color:#bbb; } .comment p, #addCommentContainer p{ font-size:18px; line-height:1.5; } #addCommentContainer input[type=text], #addCommentContainer textarea{ /* стили для области ввода */ display:block; border:1px solid #ccc; margin:5px 0 5px; padding:3px; font-size:12px; color:#555; font-family:Arial, Helvetica, sans-serif; } #addCommentContainer textarea{ width:300px; } label{ font-size:10px; } label span.error{ color:red; position:relative; right:-10px; } #submit{ /* кнопка отправки */ background-color:#58B9EB; border:1px solid #40A2D4; color:#FFFFFF; cursor:pointer; font-family:'Myriad Pro',Arial,Helvetica,sans-serif; font-size:14px; font-weight:bold; padding:4px; margin-top:5px; -moz-border-radius:4px; -webkit-border-radius:4px; border-radius:4px; } #submit:hover{ background-color:#80cdf5; border-color:#52b1e2; }
Во второй части стилевого файла мы применяем стили к комментариям и форме. Заметьте селектор input[type=text], который выбирает элементы в зависимости от атрибута type.
Шаг 4 – jQuery
Сейчас давайте разберемся с jQuery, являющимся последним шагом данного урока. После подключения библиотеки внизу страницы (для повышения скорости загрузки страницы), можно заняться написанием скрипта.
script.js
$(document).ready(function(){ /* Код выполняется, когда загружена вся страница */ /* Данный флаг предотвращает множественную отправку комментария */ var working = false; /* Прослушивание события "нажатие на кнопку" */ $('#addCommentForm').submit(function(e){ e.preventDefault(); if(working) return false; working = true; $('#submit').val('Working..'); $('span.error').remove(); /* Отправляем содержимое полей в submit.php: */ $.post('submit.php',$(this).serialize(),function(msg){ working = false; $('#submit').val('Submit'); if(msg.status){ /* / Если вставка прошла успешно, добавляем комментарий / внизу с эффектом скольжения /*/ $(msg.html).hide().insertBefore('#addCommentContainer').slideDown(); $('#body').val(''); } else { /* / Если была ошибка, проходим циклом по объекту / msg.errors и выводим их на страницу /*/ $.each(msg.errors,function(k,v){ $('label[for='+k+']').append('<span class="error">'+ v+'</span>'); }); } },'json'); }); });
Сначала мы дожидаемся загрузки всей страницы, всей объектной модели документа (DOM). Переменная working работает как флаг, который сообщает скрипту, выполняется ли Ajax-запрос (предотвращая, таким образом, множественную отправку комментария)
Затем мы проверяем статус для определения того, был ли комментарий успешно добавлен. Если да, мы выводим полученную разметку на страницу под последним комментарием с эффектом slideDown.
Если возникли проблемы, мы отображаем сообщения об ошибках, добавляя для этого элемент span к соответствующему элементу.
На этом создание простой системы комментирования с использованием Ajax завершено!
Заключение
Чтобы скрипт работал на вашем сервере, вам нужно создать таблицу comments в вашей базе данных MySQL. Вы можете сделать это, выполнив в phpMyAdmin SQL-запрос, который находится в файле table.sql, который также приложен к исходникам. После этого вам нужно внести в файл connect.php ваши данные для подключения к серверу.
P.S. Хотие освоить такие языки и технологии веб-разработки, как PHP, Javascript, Ajax, CSS и другие? Обратите внимание на премиум-уроки по различным аспектам сайтостроения. Также вам может быть интересен бесплатный курс по созданию своей CMS-системы на PHP с нуля:
По материалам tutorialzine.com
Перевод - Дмитрий
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также: