Простая система комментирования с использованием AJAX

Постоянный читатель сайта RUSELLER.COM с именем maxim (******.maxim@rambler.ru) просил перевести урок по реализации формы для комментариев. Команда сайта надеется, что данный урок поможет maxim в решении его задачи.

В данном уроке мы создадим простую систему комментариев с использованием AJAX. Система имеет интеграцию с gravatar.com и демонстрирует, как устанавливать эффективное взаимодействие между 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/">Имя пользователя</a></div>
<div title="Added at 06:40 on 30 Jun 2010" class="date">30 Jun 2010</div>
<p>Текст комментария</p>
</div>

div avatar содержит ссылку (если пользователь ввел правильный URL при размещении комментария) и изображение аватара, которое мы получаем с gravatar.com. Мы вернемся к формированию разметки на шаге PHP. В завершении следуют div name  div time и текст комментария.

Другим важным элементом в XHTML является форма комментария. Она отправляется с помощью POST. Все поля, кроме URL, должны быть заполнены.

demo.php

<div id="addCommentContainer">
<p>Добавить комментарий</p>
<form id="addCommentForm" method="post" action="">
<div>
<label for="name">Имя</label>
<input type="text" name="name" id="name" />
<label for="email">Email</label>
<input type="text" name="email" id="email" />
<label for="url">Вебсайт (не обязательно)</label>
<input type="text" name="url" id="url" />
<label for="body">Содержание комментария</label>
<textarea name="body" id="body" cols="20" rows="5"></textarea>
<input type="submit" id="submit" value="Отправить" />
</div>
</form>
</div>

Форма отправляется с помощью AJAX. Проверка выполняется в фоновом режиме в submit.php. Каждое поле имеет соответствующий элемент label, с установленным атрибутом for.

Простая система комментариев с использованием AJAX

Простая система комментариев с использованием AJAX

Шаг 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);
}

Запрос MySQL выбирает все записи из таблицы и заполняет массив $comments объектами класса comment. Данный массив выводится далее при выполнении скрипта.

demo.php

/*
/	Вывод комментариев один за другим:
*/

foreach($comments as $c){
	echo $c->markup();
}

Каждый комментарий имеет метод markup(), который генерирует правильный HTML код, готовый для вывода на страницу. Ниже приведены определения класса и метода.

Класс получает строку из базы данных (получаемую с помощью mysql_fetch_assoc() ) и сохраняет ее в переменной  $data. Она доступна только методу класса.

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:
		$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&amp;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 для представления аватара в комментариях. Gravatar - это очень полезный сервис, который устанавливает соответствие аватара с email адресом. Изображение аватара может быть легко получено с помощью передачи кодированного функцией md5() вашего email адреса на gravatar.com.

Скрипт определяет адрес URL, на котором выполняется, и определяет точный адрес изображения default_avatar.gif. Данное изображение передается на параллельно с хэшем md5, и если никакого аватар не было найдено для переданного 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'] = 'Пожалуйста, введите правильный Email.';
		}
		
		if(!($data['url'] = filter_input(INPUT_POST,'url',FILTER_VALIDATE_URL)))
		{
			// Если в поле URL был введн неправильный URL,
			// действуем так, как будто URL не был введен:
			
			$url = '';
		}
		
		// Используем фильтр с возвратной функцией:
		
		if(!($data['body'] = filter_input(INPUT_POST,'body',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
		{
			$errors['body'] = 'Пожалуйста, введите текст комментария.';
		}
		
		if(!($data['name'] = filter_input(INPUT_POST,'name',FILTER_CALLBACK,array('options'=>'Comment::validate_text'))))
		{
			$errors['name'] = 'Пожалуйста, введите имя.';
		}
		
		if(!empty($errors)){
			
			// Если есть ошибки, копируем массив $errors в $arr:
			
			$arr = $errors;
			return false;
		}
		
		// Если данные введены правильно, подчищаем данные и копируем их в $arr:
		
		foreach($data as $k=>$v){
			$arr[$k] = mysql_real_escape_string($v);
		}
		
		// email дожен быть в нижнем регистре:
		
		$arr['email'] = strtolower(trim($arr['email']));
		
		return true;
		
	}

Метод validate() (также часть класса) определен как static. Это означает, что его можно вызвать непосредственно с помощью конструкции 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 передаётся в качестве возвратной функции в два вызова 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 подготовлены для запроса mysql,
	/	но нам нужно делать вывод на экран, поэтому 
	/	готовим все элементы в массиве:
	/*/
	
	$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, в котором содержится либо разметка XHTML с вставленным комментарием, либо список ошибок. jQuery использует свойство status для определения того, что нужно выводить - либо сообщение об ошибках, либо добавлять разметку комментария к странице.

Ниже приводятся два примера.

Успешный ответ

{
    "status": 1,
    "html": "Html Code Of The Comment Comes Here..."
}

Свойство html содержит код комментария.

Ответ об ошибке

{
    "status": 0,
    "errors": {
        "email": "Please enter a valid Email.",
        "body": "Please enter a comment body.",
        "name": "Please enter a name."
    }
}

При наличии ошибки jQuery проходит циклом по объекту ошибок и выводит сообщения рядом с полями, в которых есть ошибки.

Чудесная форма запроса CSS3 & jQuery

Чудесная форма запроса CSS3 & 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{

	/*
	/	Аватар позиционируется абсолютно. 
	/	Внешнее смещение для div комментария
	/*/

	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;
}

div .comment  и #addCommentContainer имеют одинаковый стиль.  Используется несколько правил 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;
	overflow-x:hidden;
}

#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(){
	/* Следующий код выполняется только после загрузки DOM */
	
	/* Данный флаг предотвращает отправку нескольких комментариев: */
	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){

				/* 
				/	Если вставка была успешной, добавляем комментарий 
				/	ниже последнего на странице с эффектом slideDown
				/*/

				$(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');

	});
	
});

Мы используем вызов функции $(document).ready(), которая привязывает функцию к событию загрузка контента DOM. Переменная working действует как флаг, который сигнализирует о том, что запрос AJAX находится в работе (таким образом предотвращается дублирование одного и того же комментария).

В возвратной функции для запроса POST AJAX  мы проверяем свойство status, чтобы определить, был ли успешно вставлен комментарий. Если да, мы добавляем полученную разметку на страницу после последнего комментария с анимацией slideDown.

Если были проблемы, то мы выводим сообщения об ошибках, добавляя span error к соответствующему элементу label (атрибут элемента label содержит id ввода, который имеет ошибку).

Готово!

Заключение

Чтобы запустить скрипт на вашем сервере нужно создать таблицу comments в вашей базе данных MySQL. Вы можете сделать это с помощью кода SQL из файла table.sql, который надо ввести на закладке SQL в phpMyAdmin. Затем нужно установить параметры соединения с базой данных MySQL в файле connect.php.

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: tutorialzine.com/2010/06/simple-ajax-commenting-system/
Перевел: Сергей Фастунов
Урок создан: 23 Августа 2010
Просмотров: 78558
Правила перепечатки


5 последних уроков рубрики "Для сайта"

  • Эффекты блочного раскрытия

    Сегодня мы хотели бы поделиться несколькими идеями касающегося эффекта блочного раскрытия, которую вы можете использовать для своих проектов.

  • 15 полезных .htaccess сниппета для сайта на WordPress

    Если вы хотите существенно повысить уровень безопасности вашего сайта на WordPress, то вам не избежать конфигурации файла .htaccess. Это позволит не только уберечься от целого ряда хакерских атак, но и организовать перенаправления, а также решить задачи связанные с кэшем.

  • 20 бесплатных тем для WordPress в стиле Material Design

    Material Design — это набирающий обороты тренд от Google. В данной подборке собраны бесплатные темы для WordPress, выполненные в этом популярном стиле.

  • 20 сайтов с креативным MouseOver эффектом

    Эффекты на то и существуют чтобы впечатлять наших посетителей. В этой подборке собрано несколько десятков ресурсов, чьи создатели очень постарались впечатлить своих посетителей.

  • 45+ бесплатных материалов для веб дизайнеров за август 2016

    Под конец месяца предлагаем ознакомиться с набором бесплатных материалов для веб дизайнеров за прошедший месяц.

^ Наверх ^