Делаем авторизацию на Codeigniter 2.0 при помощи ajax и HMVC

в 16:06, , рубрики: ajax, codeigniter, метки: ,
Добрый день, уважаемые читатели.

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

Итак, для начала, чтобы понять, каким образом это все реализовано, нужно познакомится (для тех, кто не знаком) с расширением HMVC для Codeigniter. Сделать это можно тут.

Я попытаюсь сделать все очень наглядно, поэтому начну с файловой структуры проекта:

image

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

Вывод нашей формы авторизации мы выносим в 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

Итак, пора бы писать нашу авторизацию. При условии конечно, что перед этим вы сами её реализовали.

Давайте для начала зайдем к контроллер 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);
        });
    });

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

Буду рад услышать критику профессионалов.

Автор: Scrobot

Источник

* - обязательные к заполнению поля