bannerbannerbanner
полная версияPHP. Разработка модуля комментариев для сайта

Дмитрий Приходько
PHP. Разработка модуля комментариев для сайта

7. Контроллеры

Контроллеры в данном случае – это PHP файлы которые будут вставляться в страницы сайта и управлять выводом комментариев и авторизацией. Для данной задачи как мне кажется оптимально использовать три контроллера, размещаемых в нужных местах страницы сайта.

Контроллеры будут вставляться в необходимые места страниц сайта.

Подключение файла контроллера происходит согласно указанному к файлу пути. Есть два варианта пути: относительный и абсолютный. Относительный – это указание пути к подлючаемому файлу относительно файла с инструкцией подключения. Абсолютный – указание полного пути к подключаемому файла.

Подключение может осуществляться при помощи инструкций require или include. Они полностью идентичны за исключением лишь одной особенности – при использовании require в случае возникновения проблем выполнение скрипта будет остановлено (сценарий дальше не будет считываться), в то время как include просто выведет предупреждение и продолжит дальнейшее выполнение скрипта.

Так как по условиям задачи мы не знаем, как будет называться сайт, на котором будут размещаться комментарии и не хотим, чтобы в случае проблем с модулем сайт перестал работать, для всех дальнейших подключений будем использовать инструкцию include и указывать абсолютный путь к файлу. Абсолютный путь будем строить при помощи переменной $_SERVER['DOCUMENT_ROOT'] (см. раздел 2.4).

8. Контроллер 1

Как было определено в разделе 2.3 контроллер 1 отвечает за создание базы данных и её администратора. Все необходимые для этого файлы готовы, поэтому пишем код файла, который будет ими управлять.

Контроллер будет размещаться в самом начале страницы сайта до блока <!DOCTYPE>.

Создаем в папке «chat» файл «createbase_controller.php».

Листинг 10. createbase_controller.php Путь: news/chat/ createbase_ controller.php

<?php

error_reporting(E_ALL);

if (session_id() == '') {

session_start();

}

/* Проверяем наличие базы данных и наличие в ней админа */

try {

$dsn = new PDO('mysql:host=localhost;dbname=beseder', 'root', '');

$dsn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$dsn->exec('SET NAMES "utf8"');

} catch (PDOException $e) {

/* Мы здесь т.к. базы нет поэтому Создаем базу */

include_once $_SERVER['DOCUMENT_ROOT'] . '/chat/admin/createbase.php';

}

/* Создаем админа */

/* Проверяем передавались ли данные формы на установку админа */

/* Если ДА создаем админа */

if (isset($_POST['action']) and $_POST['action'] == 'start') {

include_once $_SERVER['DOCUMENT_ROOT'] . '/chat/admin/users/createadmin.php';

header('Location:.'); //перегружаемся чтобы убрать $_POST['action']

exit('контроллер 1 очистите кэш');

}

/* проверяем счетчик записей в таблице users */

/* если записи есть выходим, если нет вставляем форму создания админа */

try {

$count = $dsn->query("SELECT count(1) FROM users")->fetchColumn();

if ($count <= 0) {

include_once $_SERVER['DOCUMENT_ROOT']. '/chat/admin/users/form_create_admin.php';

exit('controller 1: Нет админа ');

}

} catch (PDOException $e) {

exit('Ошибка на первом входе в админку controller 1');

}

Здесь основная идея состоит в том, чтобы создавать БД на выбросе исключений в блок «catch» и последующей проверке наличия администратора при помощи счетчика записей.

Логика работы контроллера 1 следующая.

1.Запускаем сессию.

2. Пробуем подключиться к БД «beseder».

Внимание!

Не забываем ввести корректные данные строки подключения

$dsn = new PDO('mysql:host=localhost;dbname=beseder', 'root', '');

если они отличаются от установленных по умолчанию.

3. Если БД нет, получаем ошибку и создаем БД в блоке обработки исключений catch при помощи файла createbase.php

4. На этом шаге БД или уже была или только что была создана.

5. Проверяем, передавались ли данные из формы form_create_admin.php

на создание администратора, если передавались, обрабатываем их файлом createadmin.php и создаем запись данных администратора в БД.

6. Проверяем счетчик записей в таблице «users», если счетчик записей больше 1, т.е. в есть пользователи, то выходим. Контроллер выполнил работу. Есть БД и есть админ.

7. Если записи в БД отсутствуют вставляем форму для ввода данных администратора.

form_create_admin.php

заполняем значения и отправляем. Свойство «action» этой формы пустое, поэтому произойдет перезагрузка страницы и контроллер повторит свою работу, но теперь уже точно сработает п.5. и соответственно п.6. Контроллер выполнил работу. Есть БД и есть админ.

Важно! При наличии $_POST['action'] == 'start' контроллер 1 будет каждый раз создавать в таблице «users» дубликаты администратора при перезагрузке страницы, а соответственно появятся ошибки и сайт станет недоступен. Поэтому в последней строке листинга 5. createadmin.php мы обнуляем данные $_POST['action']= ''; и перезагружаем страницу в контроллере header('Location:.');exit();.

Проверяем работу контроллера. Вставляем в файл index.html т.е. главную страницу сайта «news» код:

<?php include_once $_SERVER['DOCUMENT_ROOT'].'/chat/createbase.php'?>

Вставляем в самый верх. Получится:

Листинг 11. Тестируем контроллер 1

<?php include_once $_SERVER['DOCUMENT_ROOT'].'/chat/createbase_controller.php'?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>News</title>

</head>

<body>

<p>Значимость этих проблем настолько очевидна, что начало повседневной работы по формированию позиции способствует

подготовке и реализации новых предложений!

<br>

Значимость этих проблем настолько очевидна, что повышение уровня гражданского сознания влечет за собой процесс

внедрения и модернизации модели развития.

<br> Практический опыт показывает, что рамки и место обучения кадров способствует повышению актуальности

соответствующих условий активизации.</p>

</body>

</html>

Запускаем сайт, в случае с Open Server просто кликаем по его названию в выпадающем меню. Должно получиться следующее


Рис. 14. Вывод формы создания администратора


Появляются сообщения о том, что БД и таблицы созданы и затем выводится форма для задания логина и пароля администратора модуля.

Вводим свой логин и пароль, отправляем. Получается:




Рис. 15. Работа сайта


Мы видим содержание сайта, значит все прошло успешно и контроллер 1 свою функцию выполнил. Можете войти в phpMyAdmin и проверить таблицы и записи.

9. Контроллер 2. описание

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

• Авторизация – отвечает за вход в модуль для возможности оставления комментариев ;

• Регистрация – установка параметров авторизации нового пользователя;

• Кабинет – отвечает за вход в личный кабинет пользователя;

• Выход.

Контроллер должен обеспечивать вход в личный кабинет пользователя и предоставлять ему возможности для изменения и управления данными.

В данном случае достаточно двух основных ролей пользователя: «admin» и «user». «admin» может управлять добавлением, редактированием и удалением любых пользователей, имеет доступ для редактирования и удаления всех комментариев и ответов на них, «user» имеет те же возможности, но только для себя.

Есть также дополнительный резервный профиль «Site Administrator» он не активирован.

Перед написанием кода контроллера необходимо создать файлы его окружения.

9.1 Файлы окружения контроллера 2
9.1.1 Личный кабинет

Создаем в папке «admin» файл «index.php». Это будет страница администрирования модуля, на которой будут располагаться ссылки на соответственные разделы.

Листинг 12. index.php Путь: /news/chat/admin/index.php


<?php

/* Проверяем уровень доступа к странице */


include_once $_SERVER['DOCUMENT_ROOT'] . '/chat/admin/access.php';


if (!userIsLoggedIn()) {

include $_SERVER['DOCUMENT_ROOT'] . '/chat/admin/form_login.php';

exit();

}


if (!userHasRole('admin') and !userHasRole('user')) {

$error = 'Вход только для администратора';

include $_SERVER['DOCUMENT_ROOT'].'/chat/admin/accessdenied.html.php';

exit();

}

?>

<html lang="en">


<head>

<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="/style.css" />

<title>Панель управления</title>

</head>


<body class="chatbody">

<?php include_once $_SERVER['DOCUMENT_ROOT'] . '/chat/admin/button_logout.html'; ?>

<div class="wrap_apanel">

<div class="blockapanel">

<h2>Панель управления</h2>

<ul>

<li><a href="/chat/admin/comment.php" class="apanel">Комментарии</a></li>

<li><a href="/chat/admin/users/index.php" class="apanel">Пользователи</a></li>

</ul>

 

</div>


<p><a href="/" class="apreturn">Вернуться на главную страницу</a></p>

</div>

</body>


</html>


В самом начале файла проверяем данные пользователя, если пользователь авторизован и имеет статус «admin» или «user» открываем страницу, если нет, выводим страницу запрета доступа accessdenied.html.php. Если пользователь не авторизован, выводим форму авторизации form_login.php.

На самой странице панели управления выводим:

• форму выхода пользователя из сессии button_logout.html с кнопкой «Выйти»;

• ссылки для перехода на страницы «Комментарии», «Пользователи»;

• ссылку «Вернуться на главную страницу» для перехода на начальную страницу сайта.

9.1.2 Управление доступом

Для управления доступом не будем изобретать велосипед, а воспользуемся уже проверенным решением из шуточной CMS [1] и создаем файл «access.php» листинг которого за некоторыми доработками аналогичен, приведенному в данной книге.

В исходный листинг [1.C.233] добавлены проверка активации и установление «id» пользователя.


Листинг 13. access.php Путь: /news/chat/admin/access.php


<?php

error_reporting(E_ALL);


/* Проверяем пароль и логин стартуем или удаляем сессию */

/* Функция возвращает true или false в зависимости от результатов проверки */

function userIsLoggedIn()

{

if (isset($_POST['action']) and $_POST['action'] == 'out')

{

if (!isset($_POST['login']) or $_POST['login'] == '' or

!isset($_POST['password']) or $_POST['password'] == '')

{


$GLOBALS['loginError'] = 'Пожалуйста, заполните оба поля';

return FALSE;

}


$password = md5($_POST['password'] . 'swl');


if (databaseContainsAuthor($_POST['login'], $password))

{

      /* Если пользователь существует в БД, то проверяем его активацию */


      try {

      include $_SERVER['DOCUMENT_ROOT'].'/chat/dsn.php';


      $activation ='';

      $login = $_POST['login'];

      $password = md5($_POST['password'] . 'swl');


      $sql = 'SELECT activation FROM users WHERE login = :login AND password = :password';

      $s = $dsn->prepare($sql);

      $s->bindValue(':login', $login);

      $s->bindValue(':password', $password);

      $s->execute();

      }

      catch (PDOException $e) {

            echo $e->getMessage();

            exit();

      }


      $activation = $s->fetch(PDO::FETCH_COLUMN);


      if ($activation !=1) {


            include $_SERVER['DOCUMENT_ROOT'].'/chat/admin/erroractivation.html';

            exit();

      }


      /* Если активирован задаем значения сессии */


      if(session_id() == '') {session_start();}


$_SESSION['loggedIn'] = TRUE;

$_SESSION['login'] = $_POST['login'];

$_SESSION['password'] = $password;

return TRUE;

}

else

{

      if(session_id() == '') {session_start();}


unset($_SESSION['loggedIn']);

unset($_SESSION['login']);

unset($_SESSION['password']);

$GLOBALS['loginError'] =

'Указанный логин или password не совпадают.';

return FALSE;

}

}


if (isset($_POST['action']) and $_POST['action'] == 'logout')

{

if(session_id() == '') {session_start();}


unset($_SESSION['loggedIn']);

unset($_SESSION['login']);

unset($_SESSION['password']);

unset($_SESSION['userid']);

header('Location: ' . $_POST['goto']);


exit();

}

if(session_id() == '') {session_start();}


if (isset($_SESSION['loggedIn']))

{

return databaseContainsAuthor($_SESSION['login'], $_SESSION['password']);

}

}


/* Функция проверяет наличие в БД пользователя с переданной парой логин – пароль */


function databaseContainsAuthor($login, $password)

{


include $_SERVER['DOCUMENT_ROOT'].'/chat/dsn.php';

try

{

$sql = 'SELECT COUNT(*) FROM users WHERE login = :login AND password = :password';

$s = $dsn->prepare($sql);

$s->bindValue(':login', $login);

$s->bindValue(':password', $password);

$s->execute();

}

catch (PDOException $e)

{

echo $e->getMessage();

exit();

}


$row = $s->fetch();


if ($row[0] > 0)

{

      return TRUE;

}

else

{

return FALSE;

}

}


/* Права для пользователя */


function userHasRole($role)

{

include $_SERVER['DOCUMENT_ROOT'].'/chat/dsn.php';

if (isset($_SESSION['login'])) {


try

{

$sql = "SELECT COUNT(*) FROM users

INNER JOIN authorrole ON users.id = authorid

INNER JOIN role ON roleid = role.id

WHERE login = :login AND role.id = :roleId";

$s = $dsn->prepare($sql);

$s->bindValue(':login', $_SESSION['login']);

$s->bindValue(':roleId', $role);

$s->execute();

}

catch (PDOException $e)

{

echo $e->getMessage();

echo $e->getLine();

exit('Ошибка поиска прав пользователя');

}


$row = $s->fetch();


if ($row[0] > 0)

{

return TRUE;

}

else

{

return FALSE;

}

}

}

/* Определяем id пользователя */


function userId() {

if (isset($_SESSION['login'])) {


      try {

            include $_SERVER['DOCUMENT_ROOT'].'/dsn.php';

            $sql = 'SELECT id FROM users WHERE login = :login';

            $s = $dsn->prepare($sql);


            $s->bindValue(':login',$_SESSION['login']);

            $s->execute();


            $rowid=$s->fetch();

            $_SESSION['userid'] = $rowid['id'];

      }

      catch (PDOException $e) {


            echo $e->getMessage();

            echo $e->getLine();

            exit('Ошибка добавления пользователя');

      }

}

}


Файл содержит функции для проверки данных пользователя.

Функция userIsLoggedIn()проверяет наличие и правильность данных переданных формой авторизации, активациию пользователя. В зависимости от результатов проверки этих данных устанавливает или уничтожает значения переменных сессии $_SESSION. Возвращает «true» или «false».

Для активации пользователя используется $activation. Пользователь считается активированным, если $activation = 1. Проверяем запросом к БД для указанного логина.

Функция databaseContainsAuthor() проверяет наличие в БД пользователя с переданной парой логин – пароль. Если пользователь существует возвращает «true» если нет «false».

Функция userHasRole($role)определяет уровень пользователя: «admin» или «user». В качестве параметра передается значение $role. Если $role равна значению «id» таблицы «role» установленному для данного логина при авторизации, то возвращает значение «true» иначе «false».

Функция userId() определяет «id» пользователя. Устанавливает значение переменной сессии $_SESSION['userid'].

9.1.3 Форма авторизации

Форма авторизации «form_login.php» служит для ввода логина и пароля пользователя.


Листинг 14. form_login.php Путь: /news/chat/admin/ form_login.php


<?php include_once $_SERVER['DOCUMENT_ROOT'].'/chat/admin/clean.php'; ?>

<!DOCTYPE html>

<html lang="en">


<head>

<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="/chat/style.css" />

<title>Авторизация</title>

</head>


<body>


<?php if (isset($loginError)): ?>

<p><?php htmlout($loginError); ?></p>

<?php endif; ?>


<form action="" method="post" class="chatform">


<h4 class="formname">Авторизация</h4>

<hr>


<div class="login_input">

<label for="email">Логин:

<input type="text" name="login" id="login" class="inputs">

</label>

</div>

<hr>

<div>

<label for="password">Пароль:

<input type="password" name="password" id="password">

</label>

</div>

<hr>

<div>

<input type="hidden" name="action" value="out">

<input type="submit" value="Отправить">

</div>

</form>


</body>


</html>

В самом начале файла вставляем скрипт «clean.php», который будет чистить получаемые данные ($loginError).

Выводим форму. Заполняем, отправляем данные.

9.1.4 Страница ошибки активации

Страница ошибка активации erroractivation.html. Форма будет вставляться в случае ошибки активации, а именно, если переменная активации не равна 1:

$activation != 1;

проверка ведется в скрипте access.php.


Листинг 15. erroractivation.html Путь: /news/chat/admin/ erroractivation.html


<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="/chat/style.css" />

<title>Ошибка активациии</title>

</head>

<body>

<div style="float:none; display:inline-block; ">

<h5 class="ingress" style="text-align:center;">

Вы не активировали аккаунт, <br>

проверьте сообщения в почтовом ящике,<br>

указанном вами при регистрации

</h5>

</div>

<div>

<h5 class="ingress"><a href="/">Вернуться на главную страницу</a></h5>

</div>

</body>

</html>


Здесь вопросов быть не должно. Обычная html страница без кода. Часть стилей CSS заданы непосредственно на странице.

9.1.5 Кнопка выхода из раздела администрирования

Кнопка выхода из раздела администрирования «button_logout.php»


Листинг 16. button_logout.php Путь: /news/chat/admin/ button_logout.php


<!DOCTYPE html>

<html lang="en">

<head>

<link rel="stylesheet" type="text/css" href="/chat/style.css" />

</head>


<div class="logouts">

<form action="/chat/admin/logout.php" method="post" class="logout">

<input type="hidden" name="action" value="logout" />

<input type="hidden" name="goto" value="/admin/" />

<input type="submit" name="action" value="Выйти" />

</form>

</div>

</html>


Кнопка передает данные скрипту logout.php (Листинг 25) который обнуляет соответствующие переменные сессии.

После создания этих фалов пробуем зайти на страницу администрирования

news/chat/admin и посмотреть что получилось.




Рис. 16. Форма авторизации закрывает вход в личный кабинет

Заполняем поля формы и отправляем данные.





Рис. 17. Страница личного кабинета открыта


Если всё прошло нормально открывается страница доступа к личному кабинету в административном разделе. На этой странице имеется кнопка «Выход», ссылки на страницы «Комментарии» и «Пользователи», а также ссылка «Вернуться на главную страницу».

9.1.6 Страница доступ запрещен

Сами понимаете, без такой страницы никуда.


Листинг 17. accessdenied.html.php Путь: news/chat/admin/ accessdenied.html.php


<?php

include_once $_SERVER['DOCUMENT_ROOT'].'/chat/admin/clean.php';

include_once $_SERVER['DOCUMENT_ROOT'].'/chat/admin/button_logout.html';

?>

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<title>Access Denied</title>

</head>

<body>

<h1>Доступ запрещен</h1>

<p><b><i><?php htmlout($error); ?></i></b></p>

<p><a href="/">Вернуться на главную страницу</a></p>

 

</body>

</html>

Страница будет выводиться, в случае если у пользователя нет прав для доступа к панели управления. Допустим, user захочет войти на страницу, доступную только пользователю с правами admin. «Доступ запрещен» будет выводиться по результатам проверки в файле access.php, на странице index раздела admin вместо основной страницы.

9.2. Статистика комментариев
9.2.1 Страница комментариев

Создаем страницу просмотра статистики комментариев «comment.html.php»


Листинг 18. comment.html.php Путь: news/chat/admin/ comment.html.php


<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<link rel="stylesheet" type="text/css" href="/chat/style.css" />

<title>Листинг комментариев</title>

</head>


<body class="chatbody">

<h1 class="user">Статистика комментариев</h1>


<div class="statwrap" id="">

<!– Вставляем блок формы поиска –>

<div class="statone" id="">

<?php include_once $_SERVER['DOCUMENT_ROOT'].'/chat/admin/search.html.php'; ?>

</div><!– END statone –>


<div class="stattwo" id="">

<h5 class="user">Комментарии</h5>

<?php

if (isset($says)) {

foreach ($says as $say) : ?>

<p class="stat">

<?php

echo '<span style="color:cadetblue;">' . ' ' . $say['id'] . ' ' . '</span>';

//убираем смайлы

$patterns = '/(:([^>]+):)/U';

$replace = ' smile* ';

$clean = $say['text'];

$text = preg_replace($patterns, $replace, $clean);

echo $text;


$t = time($say['saydate']);

echo '<span style="color:cadetblue;">' . ' ' . date("d.m.Y", "$t") . '</span>'; ?>

</p>


<?php endforeach;

} ?>


</div><!– END stattwo –>


<div class="statthree" id="">

<h5 class="user">Ответы на комментарии</h5>

<?php

if (isset($replys)) {

foreach ($replys as $reply) : ?>

<p class="stat"><?php

echo '<span style="color:cadetblue;">' . ' ' . $reply['replyid'] . ' ' . '<-' . ' ' . '</span>';


//убираем смайлы

$patterns = '/(:([^>]+):)/U';

$replace = ' smile* ';

$clean = $reply['replytext'];

$text = preg_replace($patterns, $replace, $clean);

echo $text;

//время

$t = time($reply['replydate']);

echo '<span style="color:cadetblue;">' . ' ' . date("d.m.Y", "$t") . '</span>'; ?>

</p>

<?php endforeach;

} ?>


</div><!– END statthree –>


</div><!– END statwrap –>

<br />

<div class="return"><a href="/chat/admin/">Вернуться</a></div>

</body>

</html>

Страница функционально состоит из трех блоков:

• Блок с данными пользователей и формой поиска.

• Блок, отображающий комментарии.

• Блок, отображающий ответы на комментарии.

Предусмотрена ссылка для возврата на предыдущую страницу «Вернуться».

Содержание блоков формируется в файле comment.php в соответствии с данными отправленными формой поиска search.html.php. По умолчанию отображаются все имеющиеся данные. Комментарии и ответы на них выводятся без картинок.

Рейтинг@Mail.ru