Система комментирования на 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
Перевод - Дмитрий
Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!
Смотрите также:



















