Добрый день, уважаемые Хабрачитатели.
Не так давно передо мной встала задача реализовать виджет авторизации на сайте. Идея не новая, я бы даже сказал банальная, но то ли я плохо гуглил, то ли решение на столько очевидное, что нет смысла об этом писать. В любом случае, хотя бы у новичков это может вызвать проблемы, именно поэтому я решил написать данную статью.
Итак, для начала, чтобы понять, каким образом это все реализовано, нужно познакомится (для тех, кто не знаком) с расширением HMVC для Codeigniter. Сделать это можно тут.
Я попытаюсь сделать все очень наглядно, поэтому начну с файловой структуры проекта:
![image](https://habrastorage.org/files/c93/697/e77/c93697e77f28466abbb2bf92e1abf980.png)
Как вы можете увидеть, я не стал указывать всю файловую систему, а то ту структуру, которая нам необходима.
Вывод нашей формы авторизации мы выносим в Modules/widgets, тем самым используя HMVC, ну а всю логику я реализовал в application/controllers и application/models. Почему я так сделал? Честно говоря, не знаю. Можно конечно все это было сделать в Modules/widgets, но я решил сделать именно так. Вам сделать по своему никто не мешает.
Итак, давайте разберем файловую систему
application/controllers/user — контроллер, в котором происходит ajax обработка события авторизации и выхода.
application/model/userModel — модель, делающая проверку на существование пользователя, и выдающая нужный массив с данными о пользователе.
application/modules/widgets/login/controllers/login — контроллер виджета, куда будут передаваться данные сессии.
application/modules/widgets/login/controllers/userLogin — вид виджета авторизации.
application/views/layout/head, application/views/layout/footer — хэдер, содержащий начало документа, и футер
application/views/header — Хэдер нашего сайта, в который и выведен виджет авторизации. У нас не указаны контроллеры, которые все это выводят, но я думаю это итак самом собой разумеющееся.
js/custom/scripts — наш файл со скриптами, где мы и будем вызывать ajax-методы.
ну и конечно библиотека jquery.
Ну и пора бы уже начать. Начнем мы с того, что создадим наш виджет в application/modules/widgets/login/controllers/login
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class CustomWidgets extends MX_Controller {
public function userLogin()
{
$this->load->view('userLogin');
}
}
Создадим вид нашего виджета:
<form role="form" id="login-form" class="login-form">
<input type="text" name="login" placeholder="Ваш логин">
<input type="password"name="pass" placeholder="Ваш пароль">
<button type="button" id="signIn">ВХОД</button>
</form>
Теперь передадим его в наш вид header:
<div id="header" class="row">
<div class="col-xs-3" id="account">
<?=Modules::run('widgets/login/login/userLogin')?>
</div>
<div class="col-xs-9">
<!--Какой то код-->
</div>
</div>
На примере моего проекта, после стилизации, конечно, должно получится что-то вроде этого:
![image](https://habrastorage.org/files/2f5/f83/45a/2f5f8345a10e4355b3775b1c64ce02a0.png)
Итак, пора бы писать нашу авторизацию. При условии конечно, что перед этим вы сами её реализовали.
Давайте для начала зайдем к контроллер user и создадим там заготовку с двумя методами:
class User extends MX_Controller {
public function __construct() {
parent::__construct();
$this->load->model('userModel');
}
public function ajax_login()
{
}
public function ajax_logout()
{
}
}
Заранее сделаем заготовку в нашей модели userModel:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class TemplateModel extends CI_Model {
// Автозагрузка базы даных
public function __construct() {
parent::__construct();
$this->load->database();
}
// Авторизация
public function check_user($log) {
}
public function user_login($login) {
}
}
Вот теперь мы готовы ajax-ом передавать данные формы. Так сделаем же это!
$(document).ready(function(){
// Ajax login
$('#account').on('click', '#signIn', function(){
var params = $('#login-form').serialize();
console.log(params); // для дебага, дабы узнать что мы передаем все то, что нужно. Потом можно убрать.
$.post('user/ajax_login', params, function(data){
if(data == 'denied') { // если не поняли, зачем здесь это условие, то поймете позже
alert('Неправильно введены логин или пароль');
} else {
$('#login-form').remove();
$('#account').append(data);
}
});
});
});
Данные мы передали, давайте же их обработаем в методе ajax_login:
public function ajax_login()
{
$log['login'] = trim(strip_tags($_POST['login']));
$log['pass'] = sha1(md5($_POST['pass']));
$check = $this->TemplateModel->check_user($log);
if($check) {
$data['user_info'] = $this->TemplateModel->user_login($log['login']);
$ses_data = array(
'login' => $data['user_info']['login'],
);
$this->session->set_userdata($ses_data);
} else {
echo 'denied';
}
}
В данный момент остаются темные пятна, но мы их сейчас разгоним. Перейдем в нашу модель, и создадим метод check_user, куда мы передаем наш массив $log
public function check_user($log) {
$this->db->where('login', $log['login']);
$this->db->where('password', $log['pass']);
$query = $this->db->get('user');
if($query->num_rows > 0) {
return TRUE;
} else {
return FALSE;
}
}
В данном методе делаем проверку существуют ли такие поля, и если их количество больше 0, то возвращаем TRUE.
Далее в массив $data['user_info'] возвращаем работу метода user_login, в который мы передаем данные массива $log['login']
public function user_login($login) {
$this->db->where('login', $login);
$query = $this->db->get('energy_user');
return $query->row_array();
}
Ну и наконец, записываем нужные нам значения в сессию. И после строчки:
$this->session->set_userdata($ses_data);
вставляем магическую строчку, которая и дает нужный нам результат:
redirect(base_url().'widgets/login/login/userLogin');
Вот, собственно, почти все, осталось только значения сессии передать в наш контроллер виджета:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class CustomWidgets extends MX_Controller {
public function userLogin()
{
$data['user_info'] = $this->session->userdata('login');
$this->load->view('userLogin',$data);
}
}
Теперь у нас все работает! Почти профит. Осталось сделать аналогичный LogOut. Далее я приведу 2 участка кода. Думаю, вы сами сообразите, куда их вставить.
Но перед этим необходимо модифицировать слегка вид нашего виджета:
<?if(!empty($user_info)):?>
<div id="userWidget">
<span>Привет, <?=$user_info?></span><br>
<a href="">перейти в личный кабинет</a>
<button type="button" href="<?=base_url()?>user/logout" id="logout">Выйти</button>
</div>
<?else:?>
<form role="form" id="login-form" class="login-form">
<input type="text" name="login" placeholder="Ваш логин">
<input type="password"name="pass" placeholder="Ваш пароль">
<button type="button" id="signIn">ВХОД</button>
</form>
<?endif;?>
А вот и 2 обещанных участка кода:
public function ajax_logout()
{
$logout = $_POST['logout'];
if($logout) {
$this->session->unset_userdata('login');
redirect(base_url().'widgets/login/login/userLogin');
}
}
$('#account').on('click', '#logout', function(){
$.post('user/logout', {logout : true}, function(data){
$('#userWidget').remove();
$('#account').append(data);
});
});
В общем, это все, о чем я хотел рассказать. Конечно, можно многое допиливать, к примеру, если находясь в личном кабинете, нечаянно или даже специально нажали кнопку выход в виджете, ну и тому подобное.
Буду рад услышать критику профессионалов.