Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


Система комментирования на 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-разметку. Вы можете видеть объявление этого метода и класса ниже.

Хостинг

Класс забирает один ряд из базы (с помощью функции 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
Перевод - Дмитрий Науменко

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх