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

от автора

Статья о том, как прикрутить 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 и радоваться жизни.

ссылка на оригинал статьи http://habrahabr.ru/post/218639/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *