Записки по Yii 1

Эту статью буду пополнять зарубками на память. Часто бывает так что на какие-то мелочи уходит много времени. Не всегда удаётся нужное отыскать в интернете. Это такой мини-сборник мини-рецептов по Yii.

Текстовое поле с маской и текстом по-умолчанию

Если в форме требуется вывести подпись (label) и текстовое поле с маской ввода и предустановленной строкой, то тут поможет стандартный виджет Yii CMaskedTextField, определённый в framework/web/widgets/CMaskedTextField.php. Мне понадобилось в предустановленный текст написать цифры, включая "9". А эта цифра предопределена как маска на все числа. Поэтому нужно переодределить числа и "высвободить" для себя девятку. Полный код, готовый для вставки в view-файл выглядит так:

<?php
     echo $form->labelEx($model,'isbn');
     $this->widget('CMaskedTextField', array(
         'model' => $model,
         'attribute' => 'isbn',
         'mask' => '978-5-4353-01ii-i',
         'charMap' => array('i' => '[0-9]')
     ));
?>

Здесь предопределена маска для ввода ISBN, где начало кода ISBN уже по-умолчанию указано (пользователю остаётся только дописать последние три цифры). По каким правилам составлять свои маски написано тут: http://digitalbush.com/projects/masked-input-plugin
В результате на странице до получения фокуса поле не заполнено и выглядит так:
После получения фокуса, отображается преднастроенный текст:
Если в Yii используется расширение YiiBooster (4.*), то код будет выглядеть так:

<?php echo $form->maskedTextFieldGroup($model, 'isbn', array(
    'widgetOptions'=>array(
         'mask' => '978-5-4353-01ii-i',
         'charMap' => array('i' => '[0-9]'),
         'htmlOptions'=>array('class'=>'span5','maxlength'=>17)
     )));
 ?>
maskedTextFieldGroup определён в /protected/extensions/bootstrap/widgets/TbActiveForm.php
А результат выглядит более привлекательно за счёт применения стилей библиотеки Bootstrap 3:
и в фокусе:

 

Добавляем перевод

Для отображения всех элементов интерфейса, а так же данных в Yii на русском языке удобнее всего добавить специальный файл с переводами и определить язык в настройках.
В файле настроек (/protected/config/main.php) в return array() добавляем

'sourceLanguage' => 'en',
'language' => 'ru',
После этого создаём файл с переводом /protected/messages/ru/main.php. В файле переводим всё, что нужно в следующем виде:

<?php
return array(
    'Create' => 'Добавить',
    'Save' => 'Сохранить',
    'Reset' => 'Сбросить'
);
После этого можно пользоваться переводом с помощью встроенного в Yii средства Yii::t(). Например для кнопок под формой во view-файле можно написать (в этом примере Yii с расширением YiiBooster 4.*):

<div class="form-actions">
     <?php $this->widget('booster.widgets.TbButton', array(
         'buttonType'=>'submit',
         'context'=>'primary',
         'icon'=>'ok white',  
         'label'=>$model->isNewRecord ? Yii::t("main", "Create") : Yii::t("main", "Save"),
     )); ?>
     <?php $this->widget('booster.widgets.TbButton', array(
         'buttonType'=>'reset',
         'icon'=>'remove',  
         'label'=>Yii::t("main", "Reset"),
     )); ?>
</div>

Выпадающий список с данными из другой таблицы

В YiiBooster 4 (по отношению к версии 2 и 3) изменили синтаксис для выпадающего списка. В этой версии YiiBooster в форме добавления книги я реализовал выпадающий список с данными из базы по доступным жанрам книг (первым значением я поставил заглушку):

<?php echo $form->dropDownListGroup($model, 'genre_id', array('widgetOptions'=>array(
     'data' => CHtml::listData(Genre::model()->findAll(), 'id', 'name'),
     'htmlOptions' => array(
         'empty' => Yii::t("main", "Select genre")
     )
   )));
?>
Этот код во view-файле позволяет подгрузить данные из модели Genre (создаётся массив из id и наименований). Чтобы эта схема заработала в модели Book, в ней определена связь по отношению к модели Genre под названием genre типа BELONGS_TO для поля genre_id из модели Book.

public function relations()
    {
        return array(
            'authorBooks' => array(self::HAS_MANY, 'AuthorBook', 'book_id'),
            'genre' => array(self::BELONGS_TO, 'Genre', 'genre_id'),
        );
    }
В свою очередь в модели Genre определена связь с моделью Book под названием books:

public function relations()
    {
        return array(
            'books' => array(self::HAS_MANY, 'Book', 'genre_id'),
        );
    }
Все эти связи сформировались автоматически средствами Gii при генерации соответствующих моделей. Предварительно в базе данных были настроены нужные индексы и связи таблиц.

Картинки в таблице

Иногда требуется вместо текста в таблице показывать картинки. С установленным дополнением YiiBooster 4 это делается с помощью виджета таблицы TbExtendedGridView с ячейкой виджетом TbImageColumn. Ниже приведён сокращённый пример, где данные с названием картинки подгружаются из таблицы, а сама картинка берётся из директории img на два уровня выше текущего положения. Если названия картинки нет, то выводится заглушка-каринка с заданным размером.

$this->widget('bootstrap.widgets.TbExtendedGridView', array(
  'id'=>'book-grid',
  'dataProvider'=>$model->search(),
  'type'=>'striped bordered condensed',
  'template'=>'{summary}{pager}{items}{pager}',
  'columns'=>array(
    array(
      'class'=>'bootstrap.widgets.TbImageColumn',
      'imagePathExpression' => function($data, $row) {
        if($row->photo)
          return "/../../img/" . $row->photo;
        else
          return '';
      },
      'emptyText' => 'Фотографии нет',
      'usePlaceHoldIt' => TRUE,
      'placeHoldItSize' => '130x200'
    ),
    array(
      'class'=>'bootstrap.widgets.TbButtonColumn',
      'template' => '{view} {update} {delete}',
      'buttons' => array(
        'view',    
        'update',
        'delete'
      ),
      'htmlOptions'=>array('style'=>'width: 60px'),
    )
  )
));

С картинкой и без картинки таблица выглядит примерно так:
Если в базе поле с названием картинки обязательное, то путь к картинке можно указать так:

'imagePathExpression'=>'"/../../img/".$data->photo'

Переключатель (checkbox) в таблице

Виджет таблица TbExtendedGridView из набора расширения
YiiBooster 4 может содержать виджет TbButtonColumn, который позволяет настроить активный булевый переключатель. Ниже приведён сокращённый вариант таблицы, где одно из полей в исходной таблице базы данных имеет значения 0 и 1, в результирующей таблице будет показан ярлычёк с крестиком или галочкой соответственно.

$this->widget('bootstrap.widgets.TbExtendedGridView', array(
  'id'=>'book-grid',
  'dataProvider'=>$model->search(),
  'type'=>'striped bordered condensed',
  'template'=>'{summary}{pager}{items}{pager}',
  'columns'=>array(
    array(
      'class' => 'bootstrap.widgets.TbToggleColumn',
      'toggleAction' => 'book/toggleAccounting',
      'name' => 'enable',
      'header' => Yii::t("main", "Enable on site"),
      'checkedButtonLabel' => Yii::t("main", "Check"),
      'uncheckedButtonLabel' => Yii::t("main", "Uncheck")
    ),
    array(
      'class'=>'bootstrap.widgets.TbButtonColumn',
      'template' => '{view} {update} {delete}',
      'buttons' => array(
        'view',    
        'update',
        'delete'
      ),
      'htmlOptions'=>array('style'=>'width: 60px'),
    )
  )
));

Но, чтобы этот виджет заработал, в контроллер нужно добавть обработчик:

public function actions() {
  return array(
    'toggleBook' => array(
      'class'=>'bootstrap.actions.TbToggleAction',
      'modelName' => 'Book'
    )
  );
}

Ajax кнопка

Задача: без перезагрузки страницы скопировать значение одного инпута, обработать в контроллере и записать значение в другой инпут. Во view файле пишем:

$this->widget('booster.widgets.TbButton', array(
      'buttonType'=>'ajaxButton',
      'context'=>'primary',
      'label'=>Yii::t("main", "Make book authors page"),
      'url' => CController::createUrl('author/makePage'),
      'ajaxOptions' => array(
          'type' => 'POST',
          'data' => array(
            'authorName' => 'js:$("input#Author_name").val()',
            'YII_CSRF_TOKEN' => Yii::app()->request->csrfToken),
          'success' => 'function(msg){
            $("input#Author_link").val(msg);
          }'
      )
    ));

В данном случае в контроллере AuthorController.php есть функция вида:


public function actionMakePage() {
  $link='111';
  echo $link;
}

Комментарии

Популярные сообщения из этого блога

Пропорциональное распределение суммы

Битрикс: своя геолокация

Bitrix24 API - разбор демо приложения третьего типа