Магазин на Yii2, часть 23. Админка: создание модуля и аутентификация админа

19.08.2019

Теги: Web-разработкаYii2АвторизацияИнтернетМагазинКаталогТоваровМодульПанельУправленияПрактикаФреймворк

Хорошо, с публичной частью сайта мы закончили, теперь займемся панелью управления. Для этого создадим модуль с помощью генератора кода Gii. Модуль можно рассматривать как миниатюрное приложение, состоящие из моделей, представлений, контроллеров и других вспомогательных компонентов. Но, в отличие от приложения, модуль нельзя развертывать отдельно, он должен находиться внутри приложения.

Создаем модуль для админки

Итак, набираем в адресной строке браузера www.server.loc/gii, переходим по ссылке Module Generator, задаем имя класса модуля и идентификатор модуля:

Module Class: app\modules\admin\Module
Module ID: admin

Добавляем в файл конфигурации config/web.php:

$config = [
    'id' => 'basic',
    /*...*/
    'aliases' => [
        /*...*/
    ],
    'modules' => [
        'admin' => [
            'class' => 'app\modules\admin\Module',
        ],
    ],
    'components' => [
        /*...*/
    ],
    /*...*/
];

Теперь панель управления доступна по адресу /admin/default/index или просто admin:

А в нашем приложении появилась еще одна директория modules:

Создаем layout-шаблон для админки

По аналогии с приложением нам нужен layout-шаблон в директории modules/admin/views/layouts, пусть это будет main.php. Добавим имя layout-шаблона в конфигурацию модуля:

$config = [
    'id' => 'basic',
    /*...*/
    'aliases' => [
        /*...*/
    ],
    'modules' => [
        'admin' => [
            'class' => 'app\modules\admin\Module',
            'layout' => 'main'
        ],
    ],
    'components' => [
        /*...*/
    ],
    /*...*/
];

И создаем файл modules/admin/views/layouts/main.php:

<?php
/* @var $this \yii\web\View */
/* @var $content string */

use yii\helpers\Html;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\helpers\Url;
use app\assets\AppAsset;

AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
    <meta charset="<?= Yii::$app->charset ?>">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <?php $this->registerCsrfMetaTags() ?>
    <title><?= Html::encode($this->title) ?> | Панель управления</title>
    <?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>

<header>
        <?php
        NavBar::begin([
            'brandLabel' => 'Панель управления',
            'brandUrl' => Url::to(['/admin/default/index']),
            'options' => [
                'class' => 'navbar-inverse',
            ],
        ]);
        echo Nav::widget([
            'options' => ['class' => 'navbar-nav'],
            'items' => [
                [
                    'label' => 'Каталог',
                    'items' => [
                        ['label' => 'Категории', 'url' => ['/admin/category/index']],
                        ['label' => 'Товары', 'url' => ['/admin/product/index']],
                    ],
                ],
                ['label' => 'Заказы', 'url' => ['/admin/order/index']],
                ['label' => 'Пользователи', 'url' => ['/admin/user/index']],
                ['label' => 'Страницы', 'url' => ['/admin/page/index']],
            ],
        ]);
        echo Nav::widget([
            'options' => ['class' => 'navbar-nav navbar-right'],
            'items' => [
                ['label' => 'Выйти', 'url' => ['/admin/auth/logout']],
            ],
        ]);
        NavBar::end();
        ?>
</header>

<div class="container">
    <?= $content; ?>
</div>

<footer class="footer">
    <div class="container">
        <p>&copy; <?= Yii::$app->params['shopName'] ?></p>
    </div>
</footer>

<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

Аутентификация администратора

Здесь все будет предельно просто. Создаем контроллер AuthController и модель LoginForm — чтобы проверять данные формы. Саму форму разместим в view-шаблоне login.php:

<?php
namespace app\modules\admin\controllers;

use Yii;
use yii\web\Controller;
use app\modules\admin\models\LoginForm;

class AuthController extends Controller {

    public function actionLogin() {
        $model = new LoginForm();
        /*
         * Если пришли post-данные, загружаем их в модель...
         */
        if ($model->load(Yii::$app->request->post())) {
            // ...и проверяем эти данные
            if ($model->validate()) {
                // данные корректные, пробуем авторизовать
                if (Yii::$app->params['adminEmail'] == $model->email
                    && Yii::$app->params['adminPassword'] == $model->password) {
                    LoginForm::login();
                    return $this->redirect('/admin/default/index');
                } else {
                    return $this->refresh();
                }
            }
        }
        return $this->render('login', ['model' => $model]);;
    }

    public function actionLogout() {
        LoginForm::logout();
        return $this->redirect('/admin/auth/login');
    }
}
<?php
namespace app\modules\admin\models;

use yii\base\Model;

class LoginForm extends Model {

    public $email;
    public $password;

    public function rules() {
        return [
            // удалим случайные пробелы для двух полей
            [['email', 'password'], 'trim'],
            // email и пароль обязательны для заполнения
            [
                ['email', 'password'],
                'required',
                'message' => 'Это поле обязательно для заполнения'
            ],
            // поле email должно быть адресом почты
            ['email', 'email'],
            // пароль не может быть короче 12 символов
            [['password'], 'string', 'min' => 12],
        ];
    }

    public function attributeLabels() {
        return [
            'username' => 'E-mail',
            'password' => 'Пароль',
        ];
    }

    public static function login() {
        $session = Yii::$app->session;
        $session->open();
        $session->set('auth_site_admin', true);
    }

    public static function logout() {
        $session = Yii::$app->session;
        $session->open();
        if ($session->has('auth_site_admin')) {
            $session->remove('auth_site_admin');
        }
    }
}
<?php
/*
 * View-шаблон, файл modules/admin/views/auth/login.php
 */
use yii\helpers\Html;
use yii\widgets\ActiveForm;

$this->title = 'Аутентификация';
?>

<div class="container">
    <?php
    $form = ActiveForm::begin();
    ?>
    <?= $form->field($model, 'email')->input('email'); ?>
    <?= $form->field($model, 'password')->input('password'); ?>
    <div class="form-group">
        <?= Html::submitButton('Отправить', ['class' => 'btn btn-primary']) ?>
    </div>
    <?php
    ActiveForm::end();
    ?>
</div>

Пароль администратора будем хранить в настройках приложения, файл config/params.php:

<?php

return [
    'adminEmail' => 'admin@example.com',
    'adminPassword' => 'qwerty123456',
    'senderEmail' => 'noreply@example.com',
    'senderName' => 'Example.com mailer',
    /*
     * Название магазина, например «Lamoda» или «WildBerries»
     */
    'shopName' => 'Магазин одежды и обуви',
    /*
     * Значения по умолчанию для мета-тегов title, keywords и description
     */
    'defaultTitle' => 'Интернет-магазин модной одежды и обуви',
    'defaultKeywords' => 'одежда, обувь, мужская, женская, детская, зимняя, летняя',
    'defaultDescription' => 'Коллекции женской, мужской, детской одежды и обуви',
    /*
     * Количество товаров на странице для постраничной навигации
     */
    'pageSize' => 2
];

Как видите, мы просто создаем элемент массива $_SESSION, пока он существует — администратор может находиться в панели управления. Теперь нам надо обеспечить проверку существования этого элемента массива перед выполнением любого action любого контроллера в модуле admin. Для этого создадим еще один контроллер AdminController, который будет родительским для всех остальных.

<?php
namespace app\modules\admin\controllers;

use yii\web\Controller;

class AdminController extends Controller {

    public function beforeAction($action) {
        $session = Yii::$app->session;
        $session->open();
        if (!$session->has('auth_site_admin')) {
            $this->redirect('/admin/auth/login');
            return false;
        }
        return parent::beforeAction($action);
    }
}

И внесем изменения в DefaultController, унаследовав его от AdminController:

<?php
namespace app\modules\admin\controllers;

class DefaultController extends AdminController {
    public function actionIndex() {
        return $this->render('index');
    }
}

Поиск: Web-разработка • Yii2 • Авторизация • Интернет магазин • Каталог товаров • Фреймворк • Практика • Сессия • Модуль • Панель управления

Каталог оборудования
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Производители
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Функциональные группы
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.