Апаем функционал модуля комментариев Часть I

 

Доброго времени суток дорогой читатель Блога RS! Сегодня мы расширим функционал нашего пользовательского модуля комментариев. Поделю этот пост на несколько частей, ибо в планах развить функционал хотя бы до уровня моего рабочего блога. А именно добавить пару новых полей, обезопасить проверками эти поля. Реализовать вывод ошибок, добавить возможность из имени автора делать ссылку на сайт автора, так же необходимо написать капчу, ну и на по следок вывести аватарки с gravatar. Сегодня мы реализуем лишь часть намеченного.

 

 

Цель

 

Давайте я опубликую цели на сегодня. Так вот чем мы займемся:

  • Добавим новые поля, емайл и сайт автора, в шаблон comm_form.html
  • Обработаем эти поля регулярными выражениями в модуле comm.php
  • Сформируем массив с ошибками в модуле comm.php
  • Выведем ошибки, если они есть, пользователю
  • Сформируем ссылку, если она есть, на сайт автора комментария

На этом мы пока тормознем. Капчу напишем в следующий раз, если Вам интересна эта информация и блог в целом, то подпишитесь на RSS ленту блога через ридер, или же по почте

 

Предисловие

 

Этот пост, как и многие другие на моем блоге, являются продолжением цикла статей "Разработка блога с нуля", поэтому если Вы на блоге впервые, то данный пост Вам может показаться бесполезным, ибо описаны правка файлов которых у Вас нет! Если Вы хотите научится, на практике, создавать свои проекты на php то читайте цикл с самого начала.

 

Правим шаблон

 

Как я уже написал выше, править будем шаблон comm_form.html. Открываем его. Я вывешу вам полностью готовый код шаблона, и поясню что в нем нового

<p>Оставить комментарий</p>
[_error]
<form action="index.php?blog=[_id]#bottom" method="post" name="form">
<input name="id_comm" type="hidden" value="[_id]">
<br>
<input class="input" name="author_comm" id="author_comm" onclick="if(document.getElementById('author_comm').value == 'Автор*')document.getElementById('author_comm').value = ''" type="text" value="Автор*">
<br>
<input class="input" name="email_comm" id="email_comm" onclick="if(document.getElementById('email_comm').value == 'E-Mail* (не публикуется)')document.getElementById('email_comm').value = ''" type="text" value="E-Mail* (не публикуется)">
<br>
<input class="input" name="site_comm" id="site_comm" type="text" value="http://">
<br>
<textarea class="input" name="txt_comm" id="txt_comm" onclick="if(document.getElementById('txt_comm').value == 'Введите текст*')document.getElementById('txt_comm').value = ''" rows="10">Введите текст*</textarea>
<br><br><input class="sub" type="submit" value="Оставить комментарий">
</form>
<a name="bottom"></a>

Давайте по порядку.

  • Я добавил в шаблон новое код-слово [_error]. Тут мы будем выводить сообщения об ошибках.
  • В атрибуте action появилось вот такое дополнение - #bottom. Мы с Вами не проходили якоря, но это не проблема сейчас пройдем.

В html есть возможность перемещаться по странице с помощью внутренних ссылок, эти внутренние ссылки называют якорем. Вы наверняка видели работу этих якорей. В FAQ'ах, на форумах, гостевых, и даже на блогах во время написание комментария, или переход к определенному комментарию. Посмотрите на шаблон, в самый низ. Вы увидите там ссылку вот такого вида

<a name="bottom"></a>

Если к концу url'а добавить "#" и значение атрибута name ссылки якоря, то есть "bottom", то при переходе по такому url

http://имя_сайта_и_др_get_переменные#bottom

Нас перекинет в ту часть страницы, где расположена эта ссылка-якорь.

Вот как это работает на примере моего блога

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

<a href="comm"></a>

стремиться находиться в самом вверху браузера. Таким образом пользователь сразу видит первый комментарий, ему не нужно крутить вертикальный скоролл! Надеюсь понятна суть якорей

  • Далее идут новые, и переделанные старые, поля. Я добавил для каждого id и небольшой javascript. JS сработает при клике (onclick) на поле, и уберет текст который там есть. Давайте поясню самый первый скрипт
onclick="if(document.getElementById('author_comm').value == 'Автор*')document.getElementById('author_comm').value = ''"

Если пользователь кликнул по полю, то идет проверка на наличие в поле текста - "Автор*". Если этот текст есть в поле, то чистим поле. Очень маленький и очень полезный скрипт

  • Ну и в самом конце добавилась ссылка-якорь, о ней я говорил выше.

Вот как сейчас выглядит форма

 

Добавляем новые колонки в базу данных

 

Перед тем как мы займемся редактированием модуля нам необходимо создать две новых колонки в базе данных. Заходим в структуру таблицы comm. После author добавляем две новых колонки email и site. Тип у них я сделал varchar 255.

 

Редактируем обработчик комментариев

 

Вот полный код обработчика в модуле comm.php

//--------------ОБРАБОТЧИК КОММЕТАРИЕВ
$date_day = date("d");//Определяем день
$date_month = date("m");//Определяем месяц
$date_year = date("Y");//Определяем год
$date_time = date("H:i");//Определяем часы и минуты
$date_comm = $date_day."/".$date_month."/".$date_year." ".$date_time;//Склеим все переменные в одну
//получим дату для записи в формате день/месяц/год часы:минуты

//Определяем посланные переменные из формы
if(isset($_POST['id_comm']))$id_comm = $_POST['id_comm'];
if(isset($_POST['txt_comm']))$txt_comm = $_POST['txt_comm'];
if(isset($_POST['author_comm']))$author_comm = $_POST['author_comm'];
if(isset($_POST['email_comm']))$email_comm = $_POST['email_comm'];
if(isset($_POST['site_comm']))$site_comm = $_POST['site_comm'];

if(isset($id_comm) & isset($txt_comm) & isset($author_comm))//Если посланные переменные определены как существующие
{
//Переводим html код (если есть) в каракозябры =)
//В общем то тут несколько лишних строк, но у меня паранойя, поэтому я проверяю ВСЕ переменные
$id_comm = htmlspecialchars($id_comm);
$txt_comm = htmlspecialchars($txt_comm);

//проверка поля 'автор'
if($author_comm != "" AND $author_comm != "Автор*")//Если поле было заполнено
{
//проверчем корректность ввода имени, только русские и английские буквы, ни каких символов кроме - _ и пробела
if(!preg_match("/^[-_0-9a-zA-Zа-яА-Я ]+$/s",$author_comm))$error_comm .= "Не правильный формат поля 'Автор'|";
//поле не должно содержать более 25 символов
if(mb_strlen($author_comm) > 25)$error_comm .= "В поле 'Автор' слишком много символов|";
}
else $error_comm .= "Вы не заполнили поле 'Автор'|";//если поле не заполнялось

//проверяем заполняли ли поле текст
if($txt_comm == "" OR $txt_comm == "Введите текст*")$error_comm .= "Вы не заполнили поле 'Текст'|";

//проверка поля емайл
if($email_comm != "" AND $email_comm != "E-Mail* (не публикуется)")//если поле было заполнено
{
//проверяем на корректность ввода (по сути отсеиваем не нужные символы в переменной)
if(!preg_match("/^[-_a-zA-Z0-9]+@[-_a-zA-Z0-9]+\.[-_a-zA-Z]+$/s",$email_comm))$error_comm .= "Вы ввели некорректный E-mail|";
}
else $error_comm .= "Вы не заполнили поле 'E-mail'|";//если поле не заполнялось

//проверка адреса сайта
if($site_comm != "" AND $site_comm != "http://")//Если поле заполнили
{
//проверяем приблизительную корректность адреса (по сути просто отсеиваем не нужные символы в переменной)
if(!preg_match("/^http:\/\/[-_a-zа-я0-9.]+\.[a-zа-я]+$/s",$site_comm))$error_comm .= "Некорректно введенный адрес сайта|";
}
else $site_comm = "";//создаем пустую, безопасную переменную для записи в БД

if(!isset($error_comm))
{
//Избавляемся от кавычки
$id_comm = str_replace("'","&#039",$id_comm);
$txt_comm = str_replace("'","&#039",$txt_comm);

$txt_comm = str_replace("\n","<BR>",$txt_comm);//Заменяем переносы строки на тег <BR>

//Добавляем сообщение в базу данных
$result_add_comm = mysql_query ("INSERT INTO comm (author,text,date_comm,blog,email,site)
VALUES ('$author_comm','$txt_comm','$date_comm','$id_comm','$email_comm','$site_comm')");

header("location: index.php?blog=$blog#bottom");//Перенаправляем пользователя
exit;//обратно к форме с комментариями
}
}
//--------------ОБРАБОТЧИК КОММЕТАРИЕВ

По порядку изменения обработчика:

if(isset($_POST['email_comm']))$email_comm = $_POST['email_comm'];
if(isset($_POST['site_comm']))$site_comm = $_POST['site_comm'];
  • Далее я удалил проверку переменной author_comm на html код. Удалил по той причине, что далее будет проводится проверка переменной с помощью регулярного выражения.
  • Вот та самая проверка переменной author_comm
    //проверка поля 'автор'
if($author_comm != "" AND $author_comm != "Автор*")//Если поле было заполнено
{
//проверчем корректность ввода имени, только русские и английские буквы, ни каких символов кроме - _ и пробела
if(!preg_match("/^[-_0-9a-zA-Zа-яА-Я ]+$/s",$author_comm))$error_comm .= "Не правильный формат поля 'Автор'|";
//поле не должно содержать более 25 символов
if(mb_strlen($author_comm) > 25)$error_comm .= "В поле 'Автор' слишком много символов|";
}
else $error_comm .= "Вы не заполнили поле 'Автор'|";//если поле не заполнялось

Для начала мы проверим заполнили ли поле вообще. Если нет то создастся переменная error_comm которая будет содержать ошибки обработчика. Если поля заполняли, то мы с помощью регулярного выражения определяем допустимые символы, а именно мы разрешаем русские и английский символы, подчеркивание ( "_" ), тире ( "-" ) и пробел. Все остальные символы не доступны, и если будут обнаружены создастся переменная error_comm с текстом ошибки.

После проверки на корректность ввода пройдет проверка на длину. Имя автора должно быть не длиннее 25 символов. Функция mb_strlen(переменная) позволяет определить сколько символов в переменной. Если в переменой больше 25 символов, то создастся переменная с ошибкой

  • Следующие нововведение это проверка наличие текста в переменной txt_comm
    //проверяем заполняли ли поле текст
if($txt_comm == "" OR $txt_comm == "Введите текст*")$error_comm .= "Вы не заполнили поле 'Текст'|";

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

  • Следующая проверка нацелена на определение, корректно ли написан емайл
    //проверка поля емайл
if($email_comm != "" AND $email_comm != "E-Mail* (не публикуется)")//если поле было заполнено
{
//проверяем на корректность ввода (по сути отсеиваем не нужные символы в переменной)
if(!preg_match("/^[-_a-zA-Z0-9]+@[-_a-zA-Z0-9]+\.[-_a-zA-Z]+$/s",$email_comm))$error_comm .= "Вы ввели некорректный E-mail|";
}
else $error_comm .= "Вы не заполнили поле 'E-mail'|";//если поле не заполнялось

Как и в случае с проверкой имени автора, тут первым делом определяется было ли заполнено поле. Если нет то обработчик выдаст ошибку. Если же был заполнен, то с помощью регулярного выражение определяется корректность ящика.

  • Последняя проверка нацелена на определение корректности ввода адреса сайта
    //проверка адреса сайта
if($site_comm != "" AND $site_comm != "http://")//Если поле заполнили
{
//проверяем приблизительную корректность адреса (по сути просто отсеиваем не нужные символы в переменной)
if(!preg_match("/^http:\/\/[-_a-zа-я0-9.]+\.[a-zа-я]+$/s",$site_comm))$error_comm .= "Некорректно введенный адрес сайта|";
}
else $site_comm = "";//создаем пустую, безопасную переменную для записи в БД

Так как адрес сайта это не обязательное поле, то не заполнение его не создаст ошибку. Поэтому проверка на корректность происходит только в случае если сайт пользователь ввел. Если проверка на корректность не пройдена, то создается переменная с ошибкой.

  • Теперь сам код который содержит запрос к БД не сработает если существует переменная error_comm
    if(!isset($error_comm))
{
...
}
  • В запросе добавлены две новые переменные ( $email_comm и $site_comm ), которые поместятся в две новые колонки ( email и site ) в БД
  • В функции header теперь есть ссылка на якорь #bottom

Вообще весь код за комментирован, проблем в освоение новых строк быть не должно.

 

Функция вывода комментариев

 

Мне придется опять выложить Вам полный код этой функции, так что мужайтесь

function comm($blog,$error)//функция вывода комментариев
{
$result_index = mysql_query("SELECT * FROM comm WHERE blog='$blog' ORDER BY id");//Выводим из базы данных все записи где blog равен ID поста
$myrow_index = mysql_fetch_array($result_index);
if($myrow_index != "")//Проверяем есть ли в базе данных записи
{//Если есть...
$sm_read = file("templates/comm.html");//...подключаем шаблон
$sm_read = implode("",$sm_read);//функция file() возвращаем массив, поэтому склеиваем его
do//Цикл do while
{
$edd_tamp = $sm_read;//Так как на придется править шаблон,
//то лучше его сохранить в отдельную переменную, иначе нам придется
//пользоваться функцией file() чаще чем 1 раз, а это нагрузка на сервер

//Замены идентификаторов на переменные из базы данных
//узнаем пустая ли пеерменная которая хранит адрес сайта
if($myrow_index[site] != "")$author = "<a href='".$myrow_index[site]."' rel='nofollow'>".$myrow_index[author]."</a>";//если не пустая формируем ссылку
else $author = $myrow_index[author];//если пустая, то просто сохраняем автора в переменной
$edd_tamp = str_replace("[_text]",$myrow_index[text],$edd_tamp);//Текст
$edd_tamp = str_replace("[_author]",$author,$edd_tamp);//Автор статьи
$edd_tamp = str_replace("[_date_b]",$myrow_index[date_comm],$edd_tamp);//Дата размещения

$comm .= $edd_tamp;// Склеиваем весь с генерированный код в одну переменную
}
while($myrow_index = mysql_fetch_array($result_index));
}
else $comm = "<p align='center'>Комментариев нет, Вы будите первым =)</p>";//Если записей нет, то вывести это сообщение

$form = file("templates/comm_form.html");//подключаем шаблон с формой
$form = implode("",$form);//функция file() возвращаем массив, поэтому склеиваем его

//Вывод ошибки
if($error != "")//если есть ошибки
{
$error = explode("|",$error);//превращаем строку в массив
$echoERROR .= "<p style='color:red;margin:0px;'>Обнаружены следующие ошибки:</p>";//заголовок
for($i=0;isset($error[$i]);$i++)//цикл формирующий список ошибок
{
if($error[$i] != "")$echoERROR .= "<p style='color:red;margin:0px;'>>$error[$i]</p>";//ошибки
}
$form = str_replace("[_error]",$echoERROR,$form);//вывод ошибок на экран
}
else $form = str_replace("[_error]","",$form);//если ошибок нет, то удаляем код-слово
//Вывод ошибки

$form = str_replace("[_id]",$blog,$form);//вклеиваем id cтатьи в форму
$comm .= $form;
return $comm;//Выводим с генерированный html код
}

Тут присутсвует несколько маленьких исправление, и одно крупное нововведение. Давайте опять по порядку:

  • У самой функции появилась новая стартовая переменная error
function comm($blog,$error)//функция вывода комментариев
{
...
}

Я думаю Вы догадываетесь зачем она нужна

  • У запроса к БД select я убрал обратную сортировку DESC теперь новый комментарий будет внизу всего списка, а не вверху как ранее
$result_index = mysql_query("SELECT * FROM comm WHERE blog='$blog' ORDER BY id");//Выводим из базы данных все записи где blog равен ID поста
  • Далее небольшое нововведение, генерация ссылки на сайт автора комментария
if($myrow_index[site] != "")$author = "<a href='".$myrow_index[site]."' rel='nofollow'>".$myrow_index[author]."</a>";//если не пустая формируем ссылку
else $author = $myrow_index[author];//если пустая, то просто сохраняем автора в переменной

С помощью условия мы определяем пустая ли переменная, если пустая то создаем переменную author и прописываем в нее данные из базы данных. Если же не пустая, то формируем ссылку. В атрибут href попадает ссылка сайта, которую указал пользователь при отправки комментария. Атрибут rel содержит значение nofollow что позволяет не учитывать ссылку поисковиком. Я думаю Вы как начинающий блоггер знаете про этот атрибут

  • Переделал замену код-слова [_author].
$edd_tamp = str_replace("[_author]",$author,$edd_tamp);//Автор статьи
//Код-слово теперь заменяется на с генерированную ранее переменную $author
  • Большое нововведение - вывод ошибки
//Вывод ошибки
if($error != "")//если есть ошибки
{
$error = explode("|",$error);//превращаем строку в массив
$echoERROR .= "<p style='color:red;margin:0px;'>Обнаружены следующие ошибки:</p>";//заголовок
for($i=0;isset($error[$i]);$i++)//цикл формирующий список ошибок
{
if($error[$i] != "")$echoERROR .= "<p style='color:red;margin:0px;'>>$error[$i]</p>";//ошибки
}
$form = str_replace("[_error]",$echoERROR,$form);//вывод ошибок на экран
}
else $form = str_replace("[_error]","",$form);//если ошибок нет, то удаляем код-слово
//Вывод ошибки

Суть проста. Определяем пустая ли переменная с ошибкой. Если нет, то делаем из нее массив с помощью функции explode("разделитель" переменная). Помните мы в тексте ошибки прописывали в конце разделитель "|"? Этот разделитель позволит теперь нам из переменной сделать массив. Далее циклом заносим ошибки в переменную echoERROR. После окончания этого цикла заменяем кодслово на эту переменную.

Если же переменная с ошибкой пуста, то просто заменяем код-слово на пустоту

 

Редактируем подключение модуля

 

Заходим в пользовательский файл index.php и редактируем подключение модуля комментариев

//МОДУЛЬ КОММЕНТОВ
if($blog)
{
include("moduls/comm.php");
if(!isset($error_comm))$error_comm = "";
$comm = comm($blog,$error_comm);//Выводим результат функции в переменную
$txt .= $comm;
}
//МОДУЛЬ КОММЕНТОВ

Если ошибок не было, то создаем переменную с ошибками и заносим туда пустоту. Думаю понятно для чего это нам нужно.

Ну что ж, если я ничего не забыл, то выглядеть это все будет приблизительно так

 

Заключение

 

Что-то каждый такой пост все дается мне сложнее и сложнее. Опять я потратил уйму времени, а рассказал всего ничего

В следующем посте мы напишем капчу для нашей формы, так что не переключайтесь и подпишитесь на RSS ленту блога через ридер, или же по почте

Если есть какие вопросы пользуйтесь формой ниже, я с удовольствием поясню Вам непонятные моменты.

Всего Вам наилучшего! У меня все!

Исходник
 

Возможно Вам будут интересны следующие заметки

Комментарии (12)

Ваше имя *
Сайт
Ваш E-mail *
Ваше сообщение *
 
Вы не подтвердили условия политики конфиденциальности.
Сергей, 28 Января 2012 г. 20:24 пишет:
Гость
Может конечно я не дочитал но при создании этой cms упущен один момент о
header (Location:) дело в том что если не создать файл .htaccess и не прописать в нем: "php_flag output_buffering On" то везде где стоит строчка header (Location:) будет выдавать ошибку ! особенно у тех кто denwerom пользуется
Rio-Shaman, 28 Января 2012 г. 23:34 пишет:
Автор
Может на старых версиях денвера и выдает ошибку, но я пользуюсь базовым пакетом уже много лет, и не испытывал никаких проблем. А если я с чем то не сталкивался, то банально не знаю о наличие таких ошибок, и уж тем более о их решениях...
Ответ для пользователя: Сергей
Rio-Shaman, 29 Января 2012 г. 23:22 пишет:
Автор
Спасибо Вам за такую поправку, может у кого-нить и будет такая ошибка, этому человеку эта информация будет очень полезной =)
Ответ для пользователя: Сергей
Сергей, 30 Января 2012 г. 19:37 пишет:
Гость
Вот у меня как раз и была ошибка, это как повезет
qwaser, 27 Февраля 2012 г. 17:54 пишет:
Гость
Спасибо
Алексей, 27 Апреля 2012 г. 18:45 пишет:
Читатель
Алексей, если тыкнуть на форму, то уберется текст, но, если тыкнуть обратно, то текст обратно не появится)
Может вы и так задумывали, но если что, то можно использовать такой подход:

<input class="input" name="author_comm" id="author_comm" onblur="if(this.value=='') this.value='Автор*'" onfocus="if(this.value=='Автор*') this.value=''"value="Автор*">

=)
Алексей, 03 Мая 2012 г. 18:54 пишет:
Читатель
Алексей, прошу прощения, но мне снова понадобился ваш файл с модулем комментов(
Rio-Shaman, 03 Мая 2012 г. 18:59 пишет:
Автор
Эммм...я ничего не понял :-D Я разве давал Вам какой то файл? Можно поподробнее о сути проблемы, если это конечно проблема...
Ответ для пользователя: Алексей
Алексей, 05 Мая 2012 г. 15:56 пишет:
Читатель
Сначала все было ок. Решил остановиться на этом моменте и не делать каптчу. Но потом денвер немного полетел. Переустановил и перестали работать комменты( Пробовал писать снова, но дойдя до этого момента, сообщения не добавляются в базу и соответственно не выводятся(
Rio-Shaman, 05 Мая 2012 г. 16:13 пишет:
Автор
Причем тут код скрипта и локальный сервер? Возможно Вы не полностью удалили слетевший денвер, и пытаетесь подключить скрипт к не существующей базе данных. Проверьте корректность подключения, других мыслей по поводу Вашей проблемы у меня нет =(
Ответ для пользователя: Алексей
AigGocha, 22 Января 2015 г. 21:17 пишет:
Читатель
Доброго времени!
Алексей извините что пришлось побеспокоить Вас. До сегодняшнего поста все получалось. Были конечно кое какие косячки, с моей стороны, справлялся сам. Все вроде правильно сделал, 10 раз перепроверил, но все равно выдает это:
Обнаружены следующие ошибки:
>Не правильный формат поля 'Автор'
в чем может быть проблема не поможете.
Спасибо!
AigGocha, 22 Января 2015 г. 21:53 пишет:
Читатель
Прошу прощения во второй части есть оказывается ответ по моей проблеме все дело было в utf, я все работаю в utf-8, сделал как Вы советуете
Если Вы работаете с utf то желательно изменить регулярку вот так:
if(!preg_match("/^[-_0-9a-zA-Zа-яА-ЯёЁ ]+$/su", $author_comm))
    $error_comm .= "Не правильный формат поля 'Автор'|";
все заработало.
Спасибо!