Pull to refresh

Авторизация через fancybox в yii

Reading time4 min
Views6.5K
Статья о том, как прикрутить fancybox-авторизацию к проекту на yii в кодировке win-1251. Если вы оказались более счастливым разработчиком, и ваш проект в utf, можете просто пропускать пункты, относящиеся к encoding hell, остальное все так же. Хотя, возможно тогда вам и не понадобится эта статья.

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



Подключаем fancybox

Скачиваем расширение fancybox, кладем в папку extensions.
Подключаем в шаблоне:

<?php
  $this->widget('application.extensions.fancybox.EFancyBox', array());
?>


Делаем в шаблоне ссылку, по которой будет вызываться наш fancybox:

<?php
  echo CHtml::link('Войти', array('/some_controller/fancy/'), array('class'=>'fancy_auth'));                        
?>


По классу ссылки fancy_auth навешиваем событие:

$(document).ready(function(){
	$(".fancy_auth").fancybox({
        'transitionIn'      : 'elastic',
        'transitionOut'     : 'elastic',
        'width'             : 345,
        'height'            : 360,
        'autoDimensions': false,
        'autoSize': false,
        'speedIn'           : '500',
        'speedOut'          : '500',
        'type'              : 'ajax',
        'closeBtn' : false
});


В основном, параметры приведены для примера. Единственное, на что стоит обратить внимание — 'type': 'ajax'. Если вы сделаете 'type': 'iframe', не будет работать код обработки успешного запроса, который я привожу ниже, а именно — код перезагрузки страницы. Если после авторизации перезагрузка вам не нужна, выбирайте тип по своему усмотрению.

Контроллер

Как видно из параметров ссылки, представление, содержащее форму авторизации, отдается методом fancy контроллера some_controller. У меня этот метод выглядит так:


public function actionFancy()
{
  $model=new UserLogin; 
  $this->performAjaxValidation($model);
  echo $this->renderPartial('_login_utf',array('model'=>$model),true,true);
}


По умолчанию, значение последнего параметра у renderPartial — false. В данном случае, для нас важно выставить его в true, потому что он отвечает за обработку методом processOutput(), который в методе render вызывается и по умолчанию, и подключает все необходимые скрипты и прочее динамическое содержимое. Без этого у нас не будет работать обработка ошибок при регистрации.

Шаблон и немного encoding hell

Если вам повезло, и у вас проект на utf-8, просто создаете нужное представление. Например, так:


<?php $form=$this->beginWidget('CActiveForm', array(
        'id'=>'user-login',
        //отправляем данные экшену, отвечающему за авторизацию
        'action' => Yii::app()->createUrl('/user/login'),
        //включаем ajax-валидацию ошибок
        'enableAjaxValidation'=>true,
        'clientOptions'=>array(
            'validateOnSubmit'=>true,
            //назначаем js функцию, которой нужно передать управление после того, как пришел ответ. 
            //более подробные пояснения и код функции будут приведены ниже
            'afterValidate' => 'js:afterValidate',
        ),
    )); ?

        <?php echo $form->labelEx($model,'username'); ?>
        <?php echo $form->textField($model,'username'); ?>
        <?php echo $form->error($model,'username'); ?>
    
        <?php echo $form->labelEx($model,'password'); ?>
        <?php echo $form->passwordField($model,'password'); ?>
        <?php echo $form->error($model,'password'); ?>
    
        <?php echo CHtml::SubmitButton('Войти и скачать', array(
                    'type' => 'POST',
                    // Результат запроса записываем в элемент, найденный
                    // по CSS-селектору #msg.
                    'update' => '#msg',
                    'class'=>'journalFancySubmit',
                    )); ?>
<?php $this->endWidget(); ?>


Если все очень печально, и ваш проект на win-1251, как и мой, то ваш шаблон отобразится квадратиками, то есть не в той кодировке. Холливарщики скажут — переделывайте срочно в utf, и будут правы, но к сожалению, часто реалии таковы, что по тем или иным причинам перенести весь проект в религиозно верную кодировку нельзя, а чтоб работало — надо. Самым простым костылем мне показалось просто сделать сам файл шаблона в кодировке utf-8. Тогда все отдается корректно.

Обработка ajax-валидации в контроллере, снова проблемы в кодировкой

Для того, чтобы контроллер корректно работал с установленной вами ajax-валидацией, нужно добавить обработку ajax-запроса в контроллере, обычно это делается так:


if (isset($_POST['ajax']) && $_POST['ajax'] === 'login-form') {
        echo CActiveForm::validate($model);
        Yii::app()->end;
      }



Но в случае win-1251 мы получим ошибку, поскольку json_encode, вызывающаяся в конце для возвращения результата валидации не хочет работать с этой кодировкой. Нужно переписать метод validate:


protected function validate($models, $attributes=null, $loadInput=true)
    {
        $result=array();
        if(!is_array($models))
            $models=array($models);
        foreach($models as $model)
        {
            if($loadInput && isset($_POST[get_class($model)]))
                $model->attributes=$_POST[get_class($model)];
            $model->validate($attributes);
            foreach($model->getErrors() as $attribute=>$errors)
                $result[CHtml::activeId($model,$attribute)]=$errors;
        }
        
        if (empty($result)) {
            $utf_result = array();
        }
        
        foreach ($result as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $inner_key => $inner_value) {
                    $utf_result[$key][$inner_key] = iconv('windows-1251', 'UTF-8', $inner_value);
                }
            } else {
                    $utf_result[$key] = iconv('windows-1251', 'UTF-8', $value);    
            }
        }
        
        return function_exists('json_encode') ? json_encode($utf_result) : CJSON::encode($utf_result);
    }


Здесь скопирован метод CActiveForm::validate и в конце добавлена перекодировка $result.

Соответственно, меняем вызов


echo CActiveForm::validate($model);

на


echo $this->validate($model);


Теперь стандартная обработка ошибок будет работать корректно.

После успешной авторизации

Авторизация прошла успешно, теперь самое время вспомнить о js-функции afterValidate, которую мы подключали в clientOptions при создании виджета формы авторизации:


'clientOptions'=>array(
            'validateOnSubmit'=>true,           
            'afterValidate' => 'js:afterValidate',


afterValidate — функция, которая будет вызвана после выполнения ajax-проверки.

Входящие параметры — (data, hasError), form — JQuery представление объекта формы, data — json-ответ от сервера, HasError — булевское значение, указывающее, были ли ошибки при валидации.
Имейте ввиду, afterValidate доступно только если validateOnSubmit установлена ​​в истину.

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

Например, у меня она выглядит примерно так:

function afterValidate(form, data, hasError) {
  if (hasError == false) {
    window.location.reload();
    parent.$.fancybox.close();
  }
}


Источники

Все решения взяты с yii-форума и stackoverflow.com и просто просуммированы в статье.

Вместо заключения

Желаю вам и себе работать только с проектами в utf-8 и радоваться жизни.
Tags:
Hubs:
-1
Comments8

Articles