Регистрация и авторизация пользователей на PHP. Часть третья
Сначала займемся реализацией работы алгоритма создания экземпляра класса модели пользователя. Но прежде, чем перейти к этому, нужно ещё раз описать, как мы себе представляем работу всей процедуры авторизации/регистрации.
Требования к процедуре регистрации пользователя
- Неавторизованному пользователю всегда будет доступна форма аутентификации на сайте.
- Пользователь может при аутентификации выбрать опцию «Запомнить меня».
- Авторизованный пользователь всегда будет видеть свой логин и кнопку выхода из аккаунта.
- Форма регистрации пользователя будет размещена на отдельной странице сайта.
- Форма регистрации будет дополнена капчей от Google.
- Данные, полученные от пользователя при регистрации, будут проверяться до отправки формы посредством JavaScript.
- Будет производиться проверка на уникальность логина пользователя.
- Логином пользователя мы будем считать его адрес электронной почты.
- Установим обязательные требования к паролю пользователя.
- При заполнении пользователем всех необходимых полей и признанием их значений корректными, форма регистрации будет отправлена на обработку.
- Пользователь будет зарегистрирован, информация о нем будет сохранена в БД, после чего он сразу же будет авторизован.
Очевидно, что начать нам, прежде всего, следует с формы аутентификации на сайте. Раз уж она должны быть доступной всегда, вынесем её в отдельный файл, который будем подключать к макету страницы. В корневом каталоге сайта создадим каталог blocks, и поместим туда файл header.php. А кроме этого, еще будем из внешних файлов подключать таблицы стилей и сценарии JavaScript.
Все формы будут обрабатываться сценарием файла /service.php
Форма аутентификации на сайте
Таким образом, наши файлы index.php и bootstrap.php несколько преобразятся.
<?php // Файл bootstrap.php // Включаем сессионную опцию use_strict_mode ini_set('session.use_strict_mode', 1); // Инициализируем константу для защиты от стороннего доступа define("LEZH", TRUE); // Определяем каталог исходных файлов нашего сайта define("SITE_DIR", __DIR__); // Определяем путь к каталогу файла с определением ядра сайта define("CORE_DIR", SITE_DIR . DIRECTORY_SEPARATOR . "modules" . DIRECTORY_SEPARATOR . "core" . DIRECTORY_SEPARATOR); // Подключаем файл с определением класса ядра нашего сайта require_once(CORE_DIR . "core.php"); // Определяем путь для подключения внешних файлов для страниц сайта define("INCLUDE_BLOCKS_PATH", SITE_DIR . DIRECTORY_SEPARATOR . "blocks" . DIRECTORY_SEPARATOR); // Инициализируем ядро сайта Core::init(); // Получаем информацию об авторизации пользователя $oCurrentUser = Core::factory("User")->getAuthUser(); ?>
В файл bootstrap.php мы добавили путь для подключения внешних блоков (меню и тому подобное).
<?php // Файл index.php require_once('bootstrap.php'); ?> <!doctype html> <html> <head> <title>Регистрация и авторизация пользователей</title> <?php // Подключаем необходимые CSS-файлы require_once(INCLUDE_BLOCKS_PATH . "css.php"); // Подключаем необходимые JS-файлы сценариев require_once(INCLUDE_BLOCKS_PATH . "scripts.php"); ?> </head> <body> <?php // Подключаем блок header для страницы require_once(INCLUDE_BLOCKS_PATH . "header.php"); ?> <main> <div class="container-fluid container-lg"> <h1>Главная страница сайта регистрации и авторизации пользователей</h1> </div> </main> </body> </html>
Теперь покажем содержимое следующих файлов:
- css.php;
- scripts.php;
- header.php.
<!-- Файл blocks/css.php --> <!-- Подключаем необходимые файлы для работы Bootstrap 4 --> <!-- CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous" /> <!-- Пользовательские таблицы стилей --> <link rel="stylesheet" href="/css/styles.css" />
<!-- Файл blocks/scripts.php --> <!-- jQuery --> <script src="https://yastatic.net/jquery/3.3.1/jquery.min.js"></script> <!-- JS Bootstrap 4 --> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script> <!-- Пользовательские JS-сценарии --> <script src="/js/scripts.js"></script>
<!-- Файл blocks/header.php --> <header class="bg-dark text-white"> <div class="container-fluid container-lg"> <nav class="navbar navbar-dark bg-dark"> <a class="navbar-brand link-decor" href="/lk.php">Личный кабинет</a> <form class="form-inline" autocomplete="off" onsubmit="return false;" method="post" action="/service.php"> <label class="sr-only" for="user_login">Логин</label> <div class="input-group mb-2 mb-lg-0 mr-sm-2"> <div class="input-group-prepend"> <div class="input-group-text">@</div> </div> <input class="form-control mr-sm-2" type="text" id="user_login" name="user_login" placeholder="Логин" aria-label="Логин" /> </div> <input class="form-control mb-2 mb-lg-0 mr-sm-2" type="password" id="user_password" name="user_password" placeholder="Пароль" aria-label="Пароль" /> <div class="form-check mb-2 mb-lg-0 mr-sm-2"> <input class="form-check-input" type="checkbox" id="user_remember" name="user_remember" /> <label class="form-check-label" for="user_remember"> Запомнить меня </label> </div> <!-- Скрытое поле формы, в котором хранится строка запроса к сценарию-обработчику --> <input type="hidden" id="user_login_request" name="request" value="user_login" / <button class="btn btn-success my-2 my-sm-0" type="submit">Войти</button> </form> </nav> </div> </header>
Пора уже взглянуть на главную страницу нашего тестового сайта. Она сейчас должна выглядеть примерно так.
Пользовательские таблицы стилей и JS-сценарии
Внимательный читатель уже заметил, что в файлах css.php и scripts.php у нас добавились еще два файла: пользовательские таблицы стилей и пользовательские JavaScript-сценарии. Уже сейчас в них тоже можно добавить кое-что.
/********* Файл /css/styles.css **********/ /***** Все ссылки в Bootstrap 4 от Twitter, почему-то, неподчеркнутые Для исправления этого добавим свои стили **************/ a.link-decor { text-decoration:underline !important; }
Теперь все ссылки, которым мы присвоим класс .link-decor, будут подчеркнуты. В том числе, и ссылка на личный кабинет пользователя.
// Файл /js/scripts.js // Используем строгий режим ECMAScript 5 "use strict"; (function($) { jQuery(function() { }); })(jQuery);
Содержимое файла пользовательских JavaScript-сценариев, пока что, такое. Будем его пополнять по мере необходимости.
Но... как бы... а кому сейчас авторизовываться на нашем сайте, если нет ни одного зарегистрированного пользователя, да и зарегистрироваться сейчас еще, пока что, невозможно. Этим и займемся.
Форма регистрации пользователя
Разместим ссылку на регистрацию пользователя под формой аутентификации.
<!-- Файл blocks/header.php --> <header class="bg-dark text-white"> <div class="container-fluid container-lg"> <nav class="navbar navbar-dark bg-dark"> <a class="navbar-brand link-decor" href="/lk.php">Личный кабинет</a> <form class="form-inline" autocomplete="off" onsubmit="return false;" method="post" action="/service.php"> <label class="sr-only" for="user_login">Логин</label> <div class="input-group mb-2 mb-lg-0 mr-sm-2"> <div class="input-group-prepend"> <div class="input-group-text">@</div> </div> <input class="form-control mr-sm-2" type="text" id="user_login" name="user_login" placeholder="Логин" aria-label="Логин" /> </div> <input class="form-control mb-2 mb-lg-0 mr-sm-2" type="password" id="user_password" name="user_password" placeholder="Пароль" aria-label="Пароль" /> <div class="form-check mb-2 mb-lg-0 mr-sm-2"> <input class="form-check-input" type="checkbox" id="user_remember" name="user_remember" /> <label class="form-check-label" for="user_remember"> Запомнить меня </label> </div> <!-- Скрытое поле формы, в котором хранится строка запроса к сценарию-обработчику --> <input type="hidden" id="user_login_request" name="request" value="user_login" / <button class="btn btn-success my-2 my-sm-0" type="submit">Войти</button> </form> </nav> <div class="row text-xl-right"> <div class="col-12"> <div class="mr-xl-3 ml-xl-0 ml-3 mb-3"> <a href="/registration.php" class="link-decor">Зарегистрироваться</a> </div> </div> </div> </div> </header>
После этого наш блок <header> будет выглядеть примено так:
Создаем в корне сайта файл registration.php со следующим содержимым.
<?php // Файл registration.php require_once('bootstrap.php'); ?> <!doctype html> <html> <head> <title>Регистрация нового пользователя</title> <?php // Подключаем необходимые CSS-файлы require_once(INCLUDE_BLOCKS_PATH . "css.php"); // Подключаем необходимые JS-файлы сценариев require_once(INCLUDE_BLOCKS_PATH . "scripts.php"); ?> </head> <body> <?php // Подключаем блок header для страницы require_once(INCLUDE_BLOCKS_PATH . "header.php"); ?> <main> <div class="container-fluid container-lg"> <h1>Регистрация пользователя сайта</h1> </div> </main> </body> </html>
Теперь нам нужно на этой странице разместить форму регистрации. Давайте подумаем, какие у неё будут поля, и как вообще она будет у нас выглядеть.
- У пользователя будет логин, которым будет являться его адрес электропочты.
- Поля нашей формы будут иметь заголовки.
- Поля формы будут иметь описания с инструкциями.
- Поля формы будут иметь поля для отображения сообщений об ошибках.
- Форма будет иметь три поля: логин, пароль и подтверждение пароля.
- Форма будет использовать капчу Google.
- Форма будет иметь три кнопки: регистрация, очистить поля, на главную.
Пока что размышлений достаточно. Приступаем. Создадим нашу форму прямо в этом же файле.
<?php // Файл registration.php require_once('bootstrap.php'); ?> <!doctype html> <html> <head> <title>Регистрация нового пользователя</title> <?php // Подключаем необходимые CSS-файлы require_once(INCLUDE_BLOCKS_PATH . "css.php"); // Подключаем необходимые JS-файлы сценариев require_once(INCLUDE_BLOCKS_PATH . "scripts.php"); ?> </head> <body> <?php // Подключаем блок header для страницы require_once(INCLUDE_BLOCKS_PATH . "header.php"); ?> <main> <div class="container-fluid container-lg"> <h1>Регистрация пользователя сайта</h1> <div id="user-registration-form"> <!-- Все поля формы обязательны для заполнения --> <form action="/service.php" autocomplete="off" method="post" onsubmit="return false;"> <!-- Поле формы --> <div class="form-group row"> <label for="user_login" class="col-md-3 col-form-label">Ваш логин:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="email" class="form-control" id="user_login" name="user_login" placeholder="Например: evgeni@lezhenkin.ru" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_login-instr">Укажите ваш действительный адрес электропочты, к которому вы имеете доступ, и на котором вы можете принимать и отправлять письма.</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_login-error"></div> </div> </div> <!-- Поле формы --> <div class="form-group row"> <label for="user_password" class="col-md-3 col-form-label">Ваш пароль:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="password" min="5" max="32" class="form-control" id="user_password" name="user_password" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_password-instr">Пароль может состоять только из символов латинского алфавита, цифр, и символов: <strong><samp>* - + ! @ # $ [ ] { } ' " ; : > < , .</samp></strong>. Пароль дожен содержать, как минимум, одну заглавную букву, и, как минимум, одну цифру. Длина пароля не должна быть менее шести символов, и не должна превышать 32 символа.</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_password-error"></div> </div> </div> <!-- Поле формы --> <div class="form-group row"> <label for="user_password_approve" class="col-md-3 col-form-label">Подтвердите введенный пароль:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="password" class="form-control" id="user_password_approve" name="user_password_approve" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_password_approve-instr">Вы должны ввести одинаковые пароли</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_password_approve-error"></div> </div> </div> <!-- Капча Google recaptcha --> <div class="form-group row"> <label for="user_captcha" class="col-md-3 col-form-label">Вы не робот?</label> <div class="col-md-9"> </div> </div> <!-- Скрытое поле формы, в котором хранится строка запроса к сценарию обработчику --> <input type="hidden" id="user_registration_request" name="request" value="user_registration" /> <!-- Кнопки управления формой --> <div class="btn-group offset-md-3"> <input type="submit" name="submit" value="Зарегистрироваться" class="ml-md-2 btn btn-success" /> <input type="reset" name="reset" value="Очистить" class="btn btn-warning" /> <a href="/" class="btn btn-danger">На главную</a> </div> </form> </div> </div> </main> </body> </html>
Пока что всё получяется не очень красивым. Давайте посмотрим.
Преображаем внешний вид формы регистрации пользователя
Размер шрифта полей подсказок, очевидно, великоват. Шрифт в полях сообщений сложно оценить, так как на данном этапе никаких ошибок нет и быть не может. Поля сообщений об ошибках вообще нужно скрыть. Отображать нужно будет только в случае наличия ошибок, и показывать не все поля, а только те, в которых будут соответствующие для пользователя сообщения. Полю описания следует дать небольшой верхний отступ от поля формы. Ну, а там, кто знает. Быть может, вам и так нравится.
/********* Файл /css/styles.css **********/ /***** Все ссылки в Bootstrap 4 от Twitter, почему-то, неподчеркнутые Для исправления этого добавим свои стили **************/ a.link-decor { text-decoration:underline !important; } /** Поля сообщений об ошибках будут отсутствовать на экране **/ div.alert.error { display:none; } /** Уменьшим размер шрифта в полях описаний и ошибок для форм **/ div.alert.error, div.alert.instr { font-size:0.75rem; } /** Поля описания будут иметь верхний отступ **/ div.alert.instr { margin-top:15px; }
Теперь страница будет выглядеть немного опрятнее. Внимательный читатель спросит, а как же быть с капчей? Действительно, давайте её подключим. Дополним код страницы registration.php кодом для генерации и вставки капчи. Обратите внимание на строки 7 и 82.
<?php // Файл registration.php require_once('bootstrap.php'); // Получаем параметры конфигурации для генерации нашей капчи $aCaptcha_Config = Core_Config::instance()->get("captcha"); ?> <!doctype html> <html> <head> <title>Регистрация нового пользователя</title> <?php // Подключаем необходимые CSS-файлы require_once(INCLUDE_BLOCKS_PATH . "css.php"); // Подключаем необходимые JS-файлы сценариев require_once(INCLUDE_BLOCKS_PATH . "scripts.php"); ?> </head> <body> <?php // Подключаем блок header для страницы require_once(INCLUDE_BLOCKS_PATH . "header.php"); ?> <main> <div class="container-fluid container-lg"> <h1>Регистрация пользователя сайта</h1> <div id="user-registration-form"> <!-- Все поля формы обязательны для заполнения --> <form action="/service.php" autocomplete="off" method="post" onsubmit="return false;"> <!-- Поле формы --> <div class="form-group row"> <label for="user_login" class="col-md-3 col-form-label">Ваш логин:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="email" class="form-control" id="user_login" name="user_login" placeholder="Например: evgeni@lezhenkin.ru" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_login-instr">Укажите ваш действительный адрес электропочты, к которому вы имеете доступ, и на котором вы можете принимать и отправлять письма.</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_login-error"></div> </div> </div> <!-- Поле формы --> <div class="form-group row"> <label for="user_password" class="col-md-3 col-form-label">Ваш пароль:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="password" min="5" max="32" class="form-control" id="user_password" name="user_password" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_password-instr">Пароль может состоять только из символов латинского алфавита, цифр, и символов: <strong><samp>* - + ! @ # $ [ ] { } ' " ; : > < , .</samp></strong>. Пароль дожен содержать, как минимум, одну заглавную букву, и, как минимум, одну цифру. Длина пароля не должна быть менее шести символов, и не должна превышать 32 символа.</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_password-error"></div> </div> </div> <!-- Поле формы --> <div class="form-group row"> <label for="user_password_approve" class="col-md-3 col-form-label">Подтвердите введенный пароль:</label> <div class="col-md-9"> <!-- Непосредственно само поле --> <input type="password" class="form-control" id="user_password_approve" name="user_password_approve" required /> <!-- Описание поля формы и требования к его заполнению --> <div class="alert alert-info instr" id="user_password_approve-instr">Вы должны ввести одинаковые пароли</div> <!-- Поле для вывода сообщения об ошибке, относящегося именно к этому полю формы --> <div class="alert alert-danger error" id="user_password_approve-error"></div> </div> </div> <!-- Капча Google recaptcha --> <div class="form-group row"> <label for="user_captcha" class="col-md-3 col-form-label">Вы не робот?</label> <div class="col-md-9"> <!-- Чтобы заработала капча Google, нужно лишь добавить одно поле --> <div class="g-recaptcha" data-sitekey="<?=$aCaptcha_Config["site_key"]?>"></div> </div> </div> <!-- Скрытое поле формы, в котором хранится строка запроса к сценарию обработчику --> <input type="hidden" id="user_registration_request" name="request" value="user_registration" /> <!-- Кнопки управления формой --> <div class="btn-group offset-md-3"> <input type="submit" name="submit" value="Зарегистрироваться" class="ml-md-2 btn btn-success" /> <input type="reset" name="reset" value="Очистить" class="btn btn-warning" /> <a href="/" class="btn btn-danger">На главную</a> </div> </form> </div> </div> </main> </body> </html>
Для того, чтобы капча генерировалась, отрисовывалась и работала как положено, необходимо подключить JavaScript-сценарий от Google. Дополним наш файл scripts.php.
<!-- Файл blocks/scripts.php --> <!-- jQuery --> <script src="https://yastatic.net/jquery/3.3.1/jquery.min.js"></script> <!-- JS Bootstrap 4 --> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script> <!-- reCAPTCHA Google --> <script src="https://www.google.com/recaptcha/api.js" async defer></script> <!-- Пользовательские JS-сценарии --> <script src="/js/scripts.js"></script>
И тут внимательный читатель, конечно же, скажет: «Так, стоп! А это что ещё такое было в строках 7 и 82?». И будет прав.
Дело в том, что различные параметры конфигурации чего-либо брать и просто так хранить в файлах со сценариями не стоит. Мы сделали так, чтобы параметры конфигурации из каталога /modules/core/config запрашивались по требованию, без нашего прямого «вмешательства».
Обновление класса Core
<?php // Файл modules/core/core.php defined("LEZH") || exit("Доступ к файлу запрещен"); /** * Класс ядра сайта будет статическим */ class Core { // Конфигурации чего-либо на нашем сайте static protected $_config = array(); /** * Инициализирует ядро сайта * ничего не возвращает */ static public function init() { // Регистрируем функции Core::_registerFunctions(); // Получаем конфигурацию подключения к СУБД // Данные для подключения хранятся внутри каталога core в каталоге config static::$_config["database"] = Core_Config::instance()->get("database"); // Подключаемся к СУБД Core_Database::instance() ->setConfig(static::$_config["database"]) ->connect(); // Стартуем сессию Core_Session::start(); } /** * Регистрируем пользовательские функции * @param string $class путь к файлу с определением класса */ static protected function _registerFunctions() { // Реализация метода _autoload spl_autoload_register(array("Core", "_autoload")); } /** * Подключает пользовательские классы */ static public function _autoload($class) { // Получаем путь к файлу с определением класса $path = static::getClassPath($class); // Подключаем файл с определением класса require_once($path); } /** * Получает путь к файлу с определением класса */ static public function getClassPath($class) { // Разбираем путь к файлу $aPathToClass = explode("_", $class); // Если имя начиналось с Core, убираем его из массива if (strtolower($aPathToClass[0]) == "core") { array_shift($aPathToClass); } // Последним элементом массива должно быть имя файла $sFileName = strtolower(array_pop($aPathToClass)); // Если нет имени файла, ничего не делаем if (empty($sFileName)) { return; } // Если есть еще элементы пути к файлу, собираем их $sPathToFile = CORE_DIR; if (!empty($aPathToClass)) { // Если есть только один элемент пути if (count($aPathToClass) == 1) { $sPathToFile .= strtolower($aPathToClass[0]) . DIRECTORY_SEPARATOR; } else { $sPathToFile .= strtolower(implode(DIRECTORY_SEPARATOR, $aPathToClass)) . DIRECTORY_SEPARATOR; } } // Если такой файл существует if (is_file($sPathToFile . $sFileName . ".php")) { $path = $sPathToFile . $sFileName . ".php"; } // Если такого файла нет, проверяем, существует ли файл описания модели elseif (is_file($sPathToFile . $sFileName . DIRECTORY_SEPARATOR . "model.php")) { $path = $sPathToFile . $sFileName . DIRECTORY_SEPARATOR . "model.php"; } else { throw new Exception("Не существует файла с определением класса <strong>" . $class . "</strong>"); } // Возвращаем путь к файлу return $path; } /** * Создает экземпляр указанного класса */ static public function factory($class, $iPrimaryKey = 0) { // Получаем путь к файлу $path = static::getClassPath($class); // Проверяем, существует ли класс с указанным именем // попробуем дополнить имя класса if (!class_exists($class)) { $class = $class . "_Model"; } return new $class($iPrimaryKey); } } ?>
В классе Core мы переписали реализацию метода init(). Здесь именно таким образом мы получаем параметры конфигурации подключения с СУБД. А выше, там где нам потребовались параметры конфигурации для подключения капчи Google, мы, воспользовавшись кодом Core_Config::instance()->get("captcha"), получили содержимое файла /modules/core/config/captcha.php. И это будут не единственные параметры конфигурации, которые мы будем запрашивать подобным образом.
Кроме этого, добавилась строка запуска сессии, за работу с которыми теперь тоже отвечает ядро. Класс Core_Session выглядит следующим образом.
Класс для работы с сессиями
<?php // Файл modules/core/session.php defined("LEZH") || exit("Доступ к файлу запрещен"); /** * Класс для работы с сессиями */ class Core_Session { // Время устаревания сессии в секундах static protected $_sessionTime = 180; /** * Стартует сессию */ static public function start() { // Если сессия еще не запущена if (session_status() !== PHP_SESSION_ACTIVE) { // Вызываем метод изменения идентификатора сессии static::sessionRegenerateId(); } // Не используем слишком старые идентификаторы сессии if (!empty($_SESSION["deleted_time"]) && $_SESSION["deleted_time"] < (time() - static::$_sessionTime)) { // Удаляем устаревшую сессию session_destroy(); // Меняем идентификатор сессии static::sessionRegenerateId(); } } /** * Обновляет идентификатор сессии */ static public function sessionRegenerateId($deleteOldSession = FALSE) { // Если сессия не запущена if (session_status() !== PHP_SESSION_ACTIVE) { // Запускает сессию session_start(); } // Устанавливаем время отсчета для удаления сессии $_SESSION["deleted_time"] = time(); // Обновляем идентификатор сессии session_regenerate_id($deleteOldSession); } } ?>
Теперь посмотрим на реализацию класса Core_Config.
<?php // Файл modules/core/config.php defined("LEZH") || exit("Доступ к файлу запрещен"); /** * Класс для обеспечения работы страницы, по сути, хранит различные данные, являясь глобальным хранилищем * Статический класс */ class Core_Config { // Полученные конфигурации static protected $_cachedConfig = array(); // Путь хранения файлов с параметрами конфигурации static protected $_path = CORE_DIR . "config" . DIRECTORY_SEPARATOR; // Экземпляр класса static protected $_instance = NULL; /** * Возвращает экземпляр класса */ static public function instance() { if (is_null(static::$_instance)) { static::$_instance = new self(); } return static::$_instance; } /** * Получает указанную конфигурацию */ public function get($configName) { // Если ранее уже была получена конфигурация, вернем её if (array_key_exists($configName, static::$_cachedConfig)) { return static::$_cachedConfig[$configName]; } // Проверяем, есть ли такая конфигурация $sFileName = strtolower(trim($configName)) . ".php"; if (is_file(static::$_path . $sFileName)) { // Сохраняем конфигурацию static::$_cachedConfig[$configName] = include_once(static::$_path . $sFileName); } // Возвращаем вызову метода полученную конфигурацию return static::$_cachedConfig[$configName]; } } ?>
На этом третью часть статьи мы завершим. Продолжим уже в следующей части, которую целиком и полностью посвятим регистрации пользователя на сайте: заполнению формы, проверки пользовательских данных, передачи пользовательских данных от браузера серверу, и самому процессу сохранения нового пользователя.