Yii2 (basic + advanced), authorization form in modal window

July 24, 2017 24 Yehor Rykhnov

Detailed instructions for adding authorization in the modal window in Yii2 (basic + advanced).

The solution contains 3 sections (instructions) for "Yii2 basic + authorization via the database in the modal window", "Yii2 basic + authorization from the box in the modal window" and "Yii2 advanced authorization in the modal window", which are combined into one article, as doing 3 separate articles does not make sense. For convenience, all code is duplicated for each step of a separate instruction. However, the solution "Yii2 basic + authorization via the database in the modal window" is taken as a basis for the remaining instructions.

Everything is checked and works.

Contents

Yii2 basic authorization via the database in the pop-up (modal) window

Step 1

To implement the authorization of Yii2 basic in the pop-up window, I'll take a previously written example with authorization from the database: Yii2 basic, authorization and registration via the database. For this we clone it and prepare it:

mkdir yii2-auth-in-modal.local
cd yii2-auth-in-modal.local
git clone https://github.com/egor/yii2-basic-auth-through-db.git .
composer update

Configuring the connection to the database and starting the migration:

yii migrate

Step 2

Create a directory for storing the app/widgets widgets and a directory for the widgets views app/widgets/views.

Create the LoginFormWidget widget to display the modal window with the authorization form, app/widgets/LoginFormWidget.php:

<?php
namespace app\widgets;
use Yii; use yii\base\Widget; use app\models\LoginForm;
class LoginFormWidget extends Widget { public function run() {
if (Yii::$app->user->isGuest) { $model = new LoginForm(); return $this->render('loginFormWidget', [ 'model' => $model, ]); } else { return ; } }
}

In the widget view LoginFormWidget, add a modal window with the authorization form, app/widgets/views/loginFormWidget.php:

<?php
use yii\helpers\Html; use yii\bootstrap\ActiveForm; use yii\bootstrap\Modal;
Modal::begin([ 'header'=>'<h4>Login</h4>', 'id'=>'login-modal', ]); ?>
<p>Please fill out the following fields to login:</p>
<?php $form = ActiveForm::begin([ 'id' => 'login-form', 'enableAjaxValidation' => true, 'action' => ['site/ajax-login'] ]); echo $form->field($model, 'email')->textInput(); echo $form->field($model, 'password')->passwordInput(); echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div> If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>. </div> <div class="form-group"> <div class="text-right">
<?php echo Html::button('Cancel', ['class' => 'btn btn-default', 'data-dismiss' => 'modal']); echo Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']); ?>
</div> </div>
<?php ActiveForm::end(); Modal::end();

Step 3

Add ajax the action of checking and authorizing the user in the controller Site, app/controllers/SiteController.php:

public function actionAjaxLogin() {
    if (Yii::$app->request->isAjax) {
        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post())) {
            if ($model->login()) {
                return $this->goBack();
            } else {
                Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
                return \yii\widgets\ActiveForm::validate($model);
            }
        }
    } else {
        throw new HttpException(404 ,'Page not found');
    }
}

Step 4

In the main layout app/views/layouts/main.php, in the use block, add the widget LoginFormWidget:

use app\widgets\LoginFormWidget;

Calling the widget LoginFormWidget is inserted after <?php $this->beginBody() ?>:

<?= (Yii::$app->user->isGuest ? LoginFormWidget::widget([]) : ''); ?>

Replace the link leading to the authorization page for calling the modal window, with:

$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];

Change to:

$menuItems[] = ['label' => 'Login', 'url' => '#', 'options' => ['data-toggle' => 'modal', 'data-target' => '#login-modal']];

As a result, app/views/layouts/main.php will look:

<?php
/* @var $this \yii\web\View */ /* @var $content string */
use yii\helpers\Html; use yii\bootstrap\Nav; use yii\bootstrap\NavBar; use yii\widgets\Breadcrumbs; use app\assets\AppAsset; use app\widgets\LoginFormWidget;
AppAsset::register($this); ?> <?php $this->beginPage() ?> <!DOCTYPE html> <html lang="<?= Yii::$app->language ?>"> <head> <meta charset="<?= Yii::$app->charset ?>"> <meta name="viewport" content="width=device-width, initial-scale=1"> <?= Html::csrfMetaTags() ?> <title><?= Html::encode($this->title) ?></title> <?php $this->head() ?> </head> <body> <?php $this->beginBody() ?> <?php if (Yii::$app->user->isGuest) { echo LoginFormWidget::widget([]); } ?> <div class="wrap"> <?php NavBar::begin([ 'brandLabel' => 'My Company', 'brandUrl' => Yii::$app->homeUrl, 'options' => [ 'class' => 'navbar-inverse navbar-fixed-top', ], ]); $menuItems = [ ['label' => 'Home', 'url' => ['/site/index']], ['label' => 'About', 'url' => ['/site/about']], ['label' => 'Contact', 'url' => ['/site/contact']], ]; if (Yii::$app->user->isGuest) { $menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']]; $menuItems[] = ['label' => 'Login', 'url' => '#', 'options' => ['data-toggle' => 'modal', 'data-target' => '#login-modal']]; } else { $menuItems[] = '<li>' . Html::beginForm(['/site/logout'], 'post') . Html::submitButton( 'Logout (' . Yii::$app->user->identity->username . ')', ['class' => 'btn btn-link logout'] ) . Html::endForm() . '</li>'; } echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => $menuItems, ]); NavBar::end(); ?>
<div class="container"> <?= Breadcrumbs::widget([ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], ]) ?> <?= $content ?> </div> </div>
<footer class="footer"> <div class="container"> <p class="pull-left">© My Company <?= date('Y') ?></p> <p class="pull-right"><?= Yii::powered() ?></p> </div> </footer>
<?php $this->endBody() ?> </body> </html> <?php $this->endPage() ?>

Save and run.

Yii2 basic, authorization from the box in the pop-up (modal) window

The example described above is also suitable for authorizing in Yii2 basic from the box with minor fix.

Step 1

Step 1 from the previous example is skipped, instead of it we set yii2 basic (Short instruction. How to install Yii 2 basic) or open an existing project with authorization out of the box.

Step 2

Execute step 2 from the previous example with some changes. In the widget view, app/widgets/views/loginFormWidget.php change:

echo $form->field($model, 'email')->textInput();

to:

echo $form->field($model, 'username')->textInput();

Because By default the login is username. Next, remove the unit responsible for resetting the password, because Out of the box it is not implemented. Everything else remains as it is.

As a result, app/widgets/LoginFormWidget.php will look like:

<?php
namespace app\widgets;
use Yii; use yii\base\Widget; use app\models\LoginForm;
class LoginFormWidget extends Widget {
public function run() { if (Yii::$app->user->isGuest) { $model = new LoginForm(); return $this->render('loginFormWidget', [ 'model' => $model, ]); } else { return ; } }
}

The view of the LoginFormWidget widget takes the form, app/widgets/views/loginFormWidget.php:

<?php
use yii\helpers\Html; use yii\bootstrap\ActiveForm; use yii\bootstrap\Modal;
Modal::begin([ 'header'=>'<h4>Login</h4>', 'id'=>'login-modal', ]); ?>
<p>Please fill out the following fields to login:</p>
<?php $form = ActiveForm::begin([ 'id' => 'login-form', 'enableAjaxValidation' => true, 'action' => ['site/ajax-login'] ]); echo $form->field($model, 'username')->textInput(); echo $form->field($model, 'password')->passwordInput(); echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div class="form-group"> <div class="text-right"> <?php echo Html::button('Cancel', ['class' => 'btn btn-default', 'data-dismiss' => 'modal']); echo Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']); ?> </div> </div>
<?php ActiveForm::end(); Modal::end();

Step 3

Step 3 from the previous example is performed completely.

As a result, actionAjaxLogin in app/controllers/SiteController.php takes the form:

public function actionAjaxLogin() {
    if (Yii::$app->request->isAjax) {
        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post())) {
            if ($model->login()) {
                return $this->goBack();
            } else {
                Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
                return \yii\widgets\ActiveForm::validate($model);
            }
        }
    } else {
        throw new HttpException(404 ,'Page not found');
    }
}

Step 4

Step 4 from the previous example will undergo minor fix. Namely, in the main layout app/views/layouts/main.php, replace the link to the authorization page with:

['label' => 'Login', 'url' => ['/site/login']]

to:

['label' => 'Login', 'url' => '#', 'options' => ['data-toggle' => 'modal', 'data-target' => '#login-modal']]

The rest is done as it is written. As a result, app/views/layouts/main.php takes the form:

<?php
/* @var $this \yii\web\View */ /* @var $content string */
use yii\helpers\Html; use yii\bootstrap\Nav; use yii\bootstrap\NavBar; use yii\widgets\Breadcrumbs; use app\assets\AppAsset; use app\widgets\LoginFormWidget;
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"> <?= Html::csrfMetaTags() ?> <title><?= Html::encode($this->title) ?></title> <?php $this->head() ?> </head> <body> <?php $this->beginBody() ?> <?= (Yii::$app->user->isGuest ? LoginFormWidget::widget([]) : ''); ?> <div class="wrap"> <?php NavBar::begin([ 'brandLabel' => 'My Company', 'brandUrl' => Yii::$app->homeUrl, 'options' => [ 'class' => 'navbar-inverse navbar-fixed-top', ], ]); echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => [ ['label' => 'Home', 'url' => ['/site/index']], ['label' => 'About', 'url' => ['/site/about']], ['label' => 'Contact', 'url' => ['/site/contact']], Yii::$app->user->isGuest ? ( ['label' => 'Login', 'url' => '#', 'options' => ['data-toggle' => 'modal', 'data-target' => '#login-modal']] ) : ( '<li>' . Html::beginForm(['/site/logout'], 'post') . Html::submitButton( 'Logout (' . Yii::$app->user->identity->username . ')', ['class' => 'btn btn-link logout'] ) . Html::endForm() . '</li>' ) ], ]); NavBar::end(); ?>
<div class="container"> <?= Breadcrumbs::widget([ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], ]) ?> <?= $content ?> </div>
</div>
<footer class="footer"> <div class="container"> <p class="pull-left">© My Company <?= date('Y') ?></p> <p class="pull-right"><?= Yii::powered() ?></p> </div> </footer>
<?php $this->endBody() ?> </body> </html> <?php $this->endPage() ?>

At the end click on Login, enter login and password (admin, admin).

Yii2 advanced. Authorization in the pop-up (modal) window

Step 1

Open an existing project on Yii2 advanced, or install a new one (Short instruction. How to install Yii2 advanced). And use the instruction described above with some changes.

Step 1 skip from the main example.

Step 2

For step 2 from the main example, change the path to the widget's storage directory and its presentation to frontend/widgets and frontend/widgets/views respectively.

In the widget class frontend/widgets/LoginFormWidget.php, we change the namespace from:

namespace app\widgets;

to:

namespace frontend\widgets;

Also, change the path to LoginForm from:

use app\models\LoginForm;

to:

use common\models\LoginForm;

In the widget view frontend/widgets/views/loginFormWidget.php change:

echo $form->field($model, 'email')->textInput();

to:

echo $form->field($model, 'username')->textInput();

Because by default the login is username.

The rest in step 2 from the main example is left as is.

Widget frontend/widgets/LoginFormWidget.php will look:

<?php
namespace frontend\widgets;
use Yii; use yii\base\Widget; use common\models\LoginForm;
class LoginFormWidget extends Widget {
public function run() { if (Yii::$app->user->isGuest) { $model = new LoginForm(); return $this->render('loginFormWidget', [ 'model' => $model, ]); } else { return ; } }
}

The view of the LoginFormWidget widget will take the form, frontend/widgets/views/loginFormWidget.php:

<?php
use yii\helpers\Html; use yii\bootstrap\ActiveForm; use yii\bootstrap\Modal;
Modal::begin([ 'header'=>'<h4>Login</h4>', 'id'=>'login-modal', ]); ?>
<p>Please fill out the following fields to login:</p>
<?php $form = ActiveForm::begin([ 'id' => 'login-form', 'enableAjaxValidation' => true, 'action' => ['site/ajax-login'], ]); echo $form->field($model, 'username')->textInput(); echo $form->field($model, 'password')->passwordInput(); echo $form->field($model, 'rememberMe')->checkbox(); ?>
<div> If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>. </div> <div class="form-group"> <div class="text-right">
<?php echo Html::button('Cancel', ['class' => 'btn btn-default', 'data-dismiss' => 'modal']); echo Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']); ?>
</div> </div>
<?php ActiveForm::end(); Modal::end();

Step 3

Step 3 from the main example we do completely.

As a result, actionAjaxLogin in frontend/controllers/SiteController.php takes the form:

public function actionAjaxLogin() {
    if (Yii::$app->request->isAjax) {
        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post())) {
            if ($model->login()) {
                return $this->goBack();
            } else {
                Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
                return \yii\widgets\ActiveForm::validate($model);
            }
        }
    } else {
        throw new HttpException(404 ,'Page not found');
    }
}

Step 4

Step 4 from the main example has small differences. Open the main layout frontend/views/layouts/main.php, add a widget to the use block with a modal window and authorization form:

use frontend\widgets\LoginFormWidget;

The rest remains as described in step 4 of the main example.

As a result, frontend/views/layouts/main.php takes the form:

<?php
/* @var $this \yii\web\View */ /* @var $content string */
use yii\helpers\Html; use yii\bootstrap\Nav; use yii\bootstrap\NavBar; use yii\widgets\Breadcrumbs; use frontend\assets\AppAsset; use common\widgets\Alert; use frontend\widgets\LoginFormWidget;
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"> <?= Html::csrfMetaTags() ?> <title><?= Html::encode($this->title) ?></title> <?php $this->head() ?> </head> <body> <?php $this->beginBody() ?> <?= (Yii::$app->user->isGuest ? LoginFormWidget::widget([]) : ''); ?> <div class="wrap"> <?php NavBar::begin([ 'brandLabel' => 'My Company', 'brandUrl' => Yii::$app->homeUrl, 'options' => [ 'class' => 'navbar-inverse navbar-fixed-top', ], ]); $menuItems = [ ['label' => 'Home', 'url' => ['/site/index']], ['label' => 'About', 'url' => ['/site/about']], ['label' => 'Contact', 'url' => ['/site/contact']], ]; if (Yii::$app->user->isGuest) { $menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']]; $menuItems[] = ['label' => 'Login', 'url' => '#', 'options' => ['data-toggle' => 'modal', 'data-target' => '#login-modal']]; } else { $menuItems[] = '<li>' . Html::beginForm(['/site/logout'], 'post') . Html::submitButton( 'Logout (' . Yii::$app->user->identity->username . ')', ['class' => 'btn btn-link logout'] ) . Html::endForm() . '</li>'; } echo Nav::widget([ 'options' => ['class' => 'navbar-nav navbar-right'], 'items' => $menuItems, ]); NavBar::end(); ?>
<div class="container"> <?= Breadcrumbs::widget([ 'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], ]) ?> <?= Alert::widget() ?> <?= $content ?> </div> </div>
<footer class="footer"> <div class="container"> <p class="pull-left">© My Company <?= date('Y') ?></p> <p class="pull-right"><?= Yii::powered() ?></p> </div> </footer>
<?php $this->endBody() ?> </body> </html> <?php $this->endPage() ?>

Adding a new user to the database. And try authorization with help modal window.

Article source: кодер.укр/записи/yii2-basic-advanced-форма-авторизации-в-модальном-окне.