Добрый день, уважаемые Хабрачитатели.
Не так давно передо мной встала задача реализовать виджет авторизации на сайте. Идея не новая, я бы даже сказал банальная, но то ли я плохо гуглил, то ли решение на столько очевидное, что нет смысла об этом писать. В любом случае, хотя бы у новичков это может вызвать проблемы, именно поэтому я решил написать данную статью.
Итак, для начала, чтобы понять, каким образом это все реализовано, нужно познакомится (для тех, кто не знаком) с расширением HMVC для Codeigniter. Сделать это можно тут.
Я попытаюсь сделать все очень наглядно, поэтому начну с файловой структуры проекта:

Как вы можете увидеть, я не стал указывать всю файловую систему, а то ту структуру, которая нам необходима.
Вывод нашей формы авторизации мы выносим в 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>
На примере моего проекта, после стилизации, конечно, должно получится что-то вроде этого:

Итак, пора бы писать нашу авторизацию. При условии конечно, что перед этим вы сами её реализовали.
Давайте для начала зайдем к контроллер 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); }); });
В общем, это все, о чем я хотел рассказать. Конечно, можно многое допиливать, к примеру, если находясь в личном кабинете, нечаянно или даже специально нажали кнопку выход в виджете, ну и тому подобное.
Буду рад услышать критику профессионалов.
