—»     —»   Мощная система для организации чата - Часть 3
  Раздел: Чаты   Комментариев: 3  

Мощная система для организации чата - Часть 3



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

Мощная система для организации чата - Часть 3

Сегодня мы выложим для вас обновленные исходники нашего растущего проекта (некоторые файлы были отредактированы, а структура базы данных малость расширена). Весь проект разложен по полочкам: системные классы будут в папке «classes», таблицы стилей в папке «css», файлы шаблона в папке «templates», и сегодня мы добавим новую папку «js» для, как вы уже догадались, файлов javascript.

Теперь скачайте исходники и давайте приступать к разработке!

Этап 1 – SQL

Сюда мы добавили новое поле для профайлов, в котором будут храниться имена. Пожалуйста, выполните следующий SQL-запрос:

ALTER TABLE `cs_profiles` ADD `first_name` varchar(255) NOT NULL default '' AFTER `name`;

Этап 2 – HTML-код

Здесь мы просто обновили шаблон с формой авторизации. Как видно, мы расширили верстку и добавили форму авторизации/регистрации:

templates/logout_form.html

<div class="column">
<h3>Powerful Chat System Demonstration</h3>
<p>Our chat will contain next features: registration, main chat, profiles with avatars, ranking system, private messaging, custom rooms, moderation / administration and possible something else (in future).</p>
</div>
<div class="column">

<div class="tabs_container">
<ul class="tabs">
<li class="active"><h3>Log In</h3></li>
<li><h3>Join</h3></li>
</ul>
</div>

<div class="nav_container">
<form class="login_form" action="index.php" method="post" id="1">
<label>Username:</label><input type="text" name="username">
<label>Password:</label><input type="password" name="password">
<input type="submit" name="Login" value="Login">
</form>
<form class="join_form" action="index.php" method="post" id="2" style="display: none;">

<label>Full name:</label>
<input type="text" id="username" name="username" placeholder="Your name" maxlength="128" title="Your name" required>

<label>First name:</label>
<input type="text" id="firstname" name="firstname" placeholder="Your first name" maxlength="128" title="Your first name">

<label>Last name:</label>
<input type="text" id="lastname" name="lastname" placeholder="Your last name" maxlength="128" title="Your last name">

<label>Email:</label>
<input type="text" id="email" name="email" placeholder="Your email" maxlength="128" title="Format: *@gmail.com" pattern=".*@gmail.com" required>

<label>Password:</label>
<input type="text" id="password" name="password" maxlength="128" title="Password" required>

<label>Repeat Password:</label>
<input type="text" id="password" name="password" maxlength="128" title="Repeat password" required oninput="checkpass(this)">

<input type="submit" name="Join" value="Join">
</form>
</div>

</div>

<script>
$(document).ready(function(){
$('.tabs li h3').click(function () {
$('.tabs li').removeClass('active');
$(this).parent().addClass('active');

$('.nav_container form').hide();
var index = $('.tabs li h3').index(this);
$('.nav_container form').eq(index).show();
return false;
});
});

function checkpass(input) {
if (input.value != document.getElementById('password').value) {
input.setCustomValidity('Password must match.');
} else {
input.setCustomValidity('');
}
}
</script>

Пожалуйста, обратите внимание на HTML-структуру формы авторизации/регистрации, она содержит несколько новых атрибутов для валидации HTML5: «заглушку», оповещение об обязательном заполнении и текстуру. Всё это выглядит очень интересно.

Этап 3 – CSS-код

Данный файл мы также обновили

css/main.css

/* page layout */
*{
margin:0;
padding:0;
}
body {
background-color:#eee;
color:#fff;
font:14px/1.3 Arial,sans-serif;
}
header {
background-color:#212121;
box-shadow: 0 -1px 2px #111111;
display:block;
height:70px;
position:relative;
width:100%;
z-index:100;
}
header h2{
font-size:22px;
font-weight:normal;
left:50%;
margin-left:-400px;
padding:22px 0;
position:absolute;
width:540px;
}
header a.stuts,a.stuts:visited{
border:none;
text-decoration:none;
color:#fcfcfc;
font-size:14px;
left:50%;
line-height:31px;
margin:23px 0 0 110px;
position:absolute;
top:0;
}
header .stuts span {
font-size:22px;
font-weight:bold;
margin-left:5px;
}

/* main styles */
.container {
background-color: #222;
color: #bbb;
margin: 20px auto;
overflow: hidden;
padding: 20px;
position: relative;
width: 800px;
}
.container h2 {
color: #fff;
margin-bottom: 10px;
}
.column {
float: left;
width: 48%;
}
.column:first-child {
margin-right: 4%;
}
.column > * {
color: #ddd;
margin-bottom: 10px;
}

/* tabs section */
.tabs_container {
margin: 0;
}
.tabs {
overflow: hidden;
}
.tabs li {
float: left;
list-style: none;
}
.tabs li h3:first-child {
margin-left: 10px
}
.tabs li h3 {
border: 1px solid #ddd;
border-bottom-width: 0;
display: block;
margin: 0 2px 0 0;
padding: 6px 10px 4px
}
.tabs li.active h3 {
background-color: #555;
border: 1px solid #ddd;
border-bottom-width: 0;

-moz-border-radius: 4px 4px 0 0;
-ms-border-radius: 4px 4px 0 0;
-o-border-radius: 4px 4px 0 0;
-webkit-border-radius: 4px 4px 0 0;
border-radius: 4px 4px 0 0;
}
.tabs li h3:hover {
background-color: #666;
cursor: pointer;
}
.tabs li.active h3:hover {
background-color: #555;
cursor: normal;
}
.nav_container form {
background-color: #555;
display: block;
padding: 15px;
}
.column h3 {
color: #fff;
}
.login_form input,.login_form label,
.join_form input,.join_form label {
display: block;
margin-bottom: 10px;
}
input[type=text], input[type=password], input[type=submit] {
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
input[type=text], input[type=password] {
font-size: 16px;
height: 25px;
margin-right: 10px;
width: 200px;
}
input[type=submit]{
cursor: pointer;
font-size: 16px;
font-weight: bold;
height: 35px;
padding: 5px;
}

/* chat block */
.chat_messages {
border: 1px solid #888;
box-shadow: 0 0 5px #AAA;
color: #000;
padding: 10px;
}
.chat_messages h2 {
color: #fff;
}
.chat_messages .message {
background-color: #fff;
margin: 5px;
padding: 5px;

-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.chat_messages .message span {
color: #444;
font-size: 10px;
margin-left: 10px;
}
.chat_submit_form {
margin: 10px 0px;
}
.chat_submit_form div {
float: left;
width: 49%;
}
.chat_submit_form .error, .chat_submit_form .success, .chat_submit_form .protect {
display: none;
}
.chat_submit_form .error {
color: #f55;
}
.chat_submit_form .success {
color: #5f5;
}
.chat_submit_form .protect {
color: #55f;
}

Этап 4 – PHP-код

Теперь давайте рассмотрим код PHP-файлов. Наш index.php был обновлен. Мы добавили функционал обработки авторизации. Перед непосредственным входом, нам нужно проверить, имеется ли в базе другой пользователь с таким же адресом электронной почты (это поле должно быть заполнено уникальным данными).

index.php

<?php

// set error reporting level
if (version_compare(phpversion(), '5.3.0', '>=') == 1)
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
else
error_reporting(E_ALL & ~E_NOTICE);

require_once('classes/Services_JSON.php');
require_once('classes/CMySQL.php'); // including service class to work with database
require_once('classes/CLogin.php'); // including service class to work with login processing

$sErrors = '';
// join processing
if (! isset($_SESSION['member_id']) && $_POST['Join'] == 'Join') {
$sUsername = $GLOBALS['MySQL']->escape($_POST['username']);
$sFirstname = $GLOBALS['MySQL']->escape($_POST['firstname']);
$sLastname = $GLOBALS['MySQL']->escape($_POST['lastname']);
$sEmail = $GLOBALS['MySQL']->escape($_POST['email']);
$sPassword = $GLOBALS['MySQL']->escape($_POST['password']);

if ($sUsername && $sEmail && $sPassword) {
// check if already exist
$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `email`='{$sEmail}'");
if ($aProfile['id'] > 0) {
$sErrors = '<h2>Another profile with same email already exist</h2>';
} else {
// generate Salt and Cached password
$sSalt = 'testing'; // TODO - we will add generation of salt in future
$sPass = sha1(md5($sPassword) . $sSalt);

// add new member into database
$sSQL = "
INSERT INTO `cs_profiles` SET
`name` = '{$sUsername}',
`first_name` = '{$sFirstname}',
`last_name` = '{$sLastname}',
`email` = '{$sEmail}',
`password` = '{$sPass}',
`salt` = '{$sSalt}',
`status` = 'active',
`role` = '1',
`date_reg` = NOW();
";
$GLOBALS['MySQL']->res($sSQL);

// autologin
$GLOBALS['CLogin']->performLogin($sUsername, $sPassword);
}
}
}

// login system init and generation code
$sLoginForm = $GLOBALS['CLogin']->getLoginBox();

$sChat = '<h2>You do not have rights to use chat</h2>';
$sInput = '';
if ($_SESSION['member_id'] && $_SESSION['member_status'] == 'active' && $_SESSION['member_role']) {
require_once('classes/CChat.php'); // including service class to work with chat

// get last messages
$sChat = $GLOBALS['MainChat']->getMessages();
if ($_GET['action'] == 'get_last_messages') { // regular updating of messages in chat
$oJson = new Services_JSON();
header('Content-type: application/json');
echo $oJson->encode(array('messages' => $sChat));
exit;
}

// get input form
$sInput = $GLOBALS['MainChat']->getInputForm();

if ($_POST['message']) { // POST-ing of message
$iRes = $GLOBALS['MainChat']->acceptMessage();

$oJson = new Services_JSON();
header('Content-type: application/json');
echo $oJson->encode(array('result' => $iRes));
exit;
}
}

// draw common page
echo strtr(file_get_contents('templates/main_page.html'), array('{form}' => $sLoginForm . $sErrors, '{chat}' => $sChat, '{input}' => $sInput));

Как видно, сегодня мы добавили функционал непосредственно самого чата.

classes/CLogin.php

<?php

class CLogin {

// constructor
function CLogin() {
session_start();
}

// get login box function
function getLoginBox() {
if (isset($_GET['logout'])) { // logout processing
if (isset($_SESSION['member_name']) && isset($_SESSION['member_pass']))
$this->performLogout();
}

if ($_POST && $_POST['Login'] == 'Login' && $_POST['username'] && $_POST['password']) { // login processing
if ($this->checkLogin($_POST['username'], $_POST['password'], false)) { // successful login
$this->performLogin($_POST['username'], $_POST['password']);
header( "Location:{$_SERVER['REQUEST_URI']}" );
exit;
} else { // wrong login
return file_get_contents('templates/login_form.html') . '<h2>Username or Password is incorrect</h2>';
}
} else { // in case if we already logged (on refresh page):
if (isset($_SESSION['member_name']) && $_SESSION['member_name'] && $_SESSION['member_pass']) {
$aReplaces = array(
'{name}' => $_SESSION['member_name'],
'{status}' => $_SESSION['member_status'],
'{role}' => $_SESSION['member_role'],
);
return strtr(file_get_contents('templates/logout_form.html'), $aReplaces);
}

// otherwise - draw login form
return file_get_contents('templates/login_form.html');
}
}

// perform login
function performLogin($sName, $sPass) {
$this->performLogout();

// make variables safe
$sName = $GLOBALS['MySQL']->escape($sName);

$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `name`='{$sName}'");
// $sPassEn = $aProfile['password'];
$iPid = $aProfile['id'];
$sSalt = $aProfile['salt'];
$sStatus = $aProfile['status'];
$sRole = $aProfile['role'];

$sPass = sha1(md5($sPass) . $sSalt);

$_SESSION['member_id'] = $iPid;
$_SESSION['member_name'] = $sName;
$_SESSION['member_pass'] = $sPass;
$_SESSION['member_status'] = $sStatus;
$_SESSION['member_role'] = $sRole;
}

// perform logout
function performLogout() {
unset($_SESSION['member_id']);
unset($_SESSION['member_name']);
unset($_SESSION['member_pass']);
unset($_SESSION['member_status']);
unset($_SESSION['member_role']);
}

// check login
function checkLogin($sName, $sPass, $isHash = true) {
// make variables safe
$sName = $GLOBALS['MySQL']->escape($sName);
$sPass = $GLOBALS['MySQL']->escape($sPass);

$aProfile = $GLOBALS['MySQL']->getRow("SELECT * FROM `cs_profiles` WHERE `name`='{$sName}'");
$sPassEn = $aProfile['password'];

if ($sName && $sPass && $sPassEn) {
if (! $isHash) {
$sSalt = $aProfile['salt'];
$sPass = sha1(md5($sPass) . $sSalt);
}
return ($sPass == $sPassEn);
}
return false;
}
}

$GLOBALS['CLogin'] = new CLogin();

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

Посмотреть демо | Скачать архив
Внимание! У вас нет прав для просмотра скрытого текста.


Заключение

Надеемся, что наше руководство будет полезным для вас, и вы используете его в своих будущих проектах. Удачи! И не забываем следить за новостями!
Обнаружили ошибку или мёртвую ссылку?
Выделите проблемный фрагмент мышкой и нажмите CTRL+ENTER.
В появившемся окне опишите проблему и отправьте уведомление Администрации ресурса.
Нужна органическая вечная ссылка из данной статьи? Постовой?
Подробности здесь
Вам понравился материал? Поблагодарить легко!
Будем весьма признательны, если поделитесь этой статьей в социальных сетях:

Ключевые тэги: ajax, PHP, MySQL, javascript, общение онлайн
Опубликовал Design FactoRy   Прочитано (раз): 4052   |   Оставлено комментариев: 3
Автор перевода — CoolWebmasters.Com ©   |   Источник материала / оригинал статьи   Распечатать
Другие статьи и новости по теме:
Комментарий #1: 10 февраля 2012 @ 14:56
Написал: senator3821 — группа: Гости  
На сайте с: --   |   Публикаций: 0   |   Комментариев: 0
ICQ: --- не указано ---
Ураа, наконец-то третья часть, спасибо сайту и автору за оперативное и максимально быстрое размещение данной информации, как раз то, что мне было нужно ))
Комментарий #2: 10 февраля 2012 @ 14:59
Написал: ITS — группа: Читатели  
На сайте с: 20.02.2010   |   Публикаций: 3   |   Комментариев: 127
ICQ: 366337851
Design FactoRy, статья хорошая =)
и попутный вопрос =)
а четвёртая часть нас - читателей - ждёт?


--------------------
Вещам, которым надо бы учиться, чтобы их делать, — лучше учиться, делая их.
© Аристотель
Комментарий #3: 10 февраля 2012 @ 15:10
Написал: Design FactoRy — группа: Администраторы  
На сайте с: 21.07.2009   |   Публикаций: 3300   |   Комментариев: 500
ICQ: --- не указано ---
ITS, естественно. Как только выйдет в оригинале - сразу переведем и опубликуем у нас.
Добавление комментария
Уважаемые пользователи!
При добавлении комментариев на сайт Вам следует учитывать следующее - все комментарии проверяются Администрацией на предмет отсутствия спама. При обнаружении признаков спама, в оставленном Вами комментарии, сам комментарий будет незамедлительно удалён, а Ваш IP-адрес будет забанен без предупреждения! Учётные записи пользователей, рассылающих спам, блокируются/удаляются без права последующего восстановления.

С уважением, Администрация сайта.
* = поля обязательны к заполнению
Полужирный Наклонный текст Подчеркнутый текст Зачеркнутый текст | Выравнивание по левому краю По центру Выравнивание по правому краю | Вставка смайликов Выбор цвета | Скрытый текст Вставка цитаты Преобразовать выбранный текст из транслитерации в кириллицу Вставка спойлера
Вопрос : Назовите месяц October по-русски
Подтверждение кода безопасности :

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


Популярные публикации


















Свежие шаблоны сайтов каждый день
С миру по нитке
«    Май 2017    »
ПнВтСрЧтПтСбВс
1234567
891011121314
15161718192021
22232425262728
293031