Архив рубрики: Yii code

Автозаполнение поля textfield

Ищем по ФИО и логину пользователя. В примере работает шаблон вида: «fio, (login)». Например: Василий Пупкин (vaseok)

Само текстовое поле где будет работать автозаполнение:

<?php echo CHtml::textfield('logins_and_fios','',array('autocomplete'=>'off','data-provide'=>'typeahead','data-items'=>4,'data-source'=>'["Вася Пупкин (Vaseok)","Стас Михайлов (fool)","Александр Васильев, (ruleezz)"]','placeholder'=>'ФИО, (Логин)'));?>

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

<script>
 $('#logins_and_fios').change(function(){
 var fiologin = $('#logins_and_fios').val();
 $.ajax({
 type: 'POST',
 data: {'fiologin':fiologin},
 url: '<?php echo Yii::app()->createAbsoluteUrl("/admin/blockedUsers/getIdByFioLogin"); ?>',
 success: function(data) {
 if (parseInt(data)>0){
 $('#BlockedUsers_blocked_user').val(data);
 }else{
 alert('Ошибка, попробуйте еще раз ввести автора.');
 }
 },
 error: function(){
 alert('Ошибка, попробуйте еще раз ввести автора.');
 }
 });
 });
</script>

А в админ/контроллере создаем функцию в данном случае getIdByFioLogin. Функция принимает строку, разбивает ее, находит нужного пользователя и возвращает его id иначе возвращает 0.


public function actionGetIdByFioLogin(){
$fiologin = $_POST['fiologin'];

$data = explode(',',$fiologin);

$fio = $data[0];
$fio = trim($fio);
$login = $data[1];
$login = str_replace('(','',$login);
$login = str_replace(')','',$login);
$login = trim($login);
$user = Users::model()->find("user_fio ='".$fio."' and user_login='".$login."'");
if ($user){
echo $user->user_id;
}else{
echo 0;
}

return;
}

Удобная сортировка записей

Появилась необходимость сортировать записи в админке. Безусловно проще сделать текстовое поле, в котором будем прописывать порядковый номер записи, но мы простых путей не ищем 🙂 Выбор пал на jQuery плагин sortable: http://joxi.ru/nAy6Lz1hYW1jrZ .
То есть просто берем и перетягиваем запись вверх или вниз. Итак, у нас есть табличка club_forum_parts, в которой есть 3 поля: part_id, part_sort и part_name, где part_sort и есть поле, отвечающее за сортировку.
В модельке, в функции search добавляем сортировочку по полю part_sort:
$criteria->order = ‘part_sort ASC’;

    public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.

$criteria=new CDbCriteria;

$criteria->compare('part_id',$this->part_id);
$criteria->compare('part_sort',$this->part_sort);
$criteria->compare('part_name',$this->part_name,true);
$criteria->order = 'part_sort ASC';

return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}

Далее идем во вьюшку и тут начинают твориться чудеса:

<?php
$this->breadcrumbs=array(
'Разделы форума',
);

$table_id = 'forum-parts'; // указываем ID нашей таблички
$action_url = '/admin/forumParts/sort'; // указываем action, в котором будем сохранять наши отсортированные поля

// Далее идет код, в котором можно и не разбираться =)
$str_js = "
var fixHelper = function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
};

$('#".$table_id."-grid table.table tbody').sortable({
forcePlaceholderSize: true,
forceHelperSize: true,
items: 'tr',
update : function () {
serial = $('#".$table_id."-grid table.table tbody').sortable('serialize', {key: 'items[]', attribute: 'class'});
$.ajax({
'url': \"$action_url\",
'type': 'post',
'data': serial,
'success': function(data){
},
'error': function(request, status, error){
alert('Что-то пошло не так. Попробуйте выполнить сортировку чуть позже.');
}
});
},
helper: fixHelper
}).disableSelection();
";
Yii::app()->clientScript->registerCoreScript('jquery.ui'); // подключаем jQuery user interface
Yii::app()->clientScript->registerScript('sortable-'.$table_id, $str_js); // Выводим написанный выше JS код
Yii::app()->clientScript->registerCss('css','.cursor { cursor: pointer; }'); // Меняем курсор над строчкой записи. Ну он же должен выглядеть как указатель?
?>

<h3>Разделы форума</h3>
<?php echo CHtml::link('Добавить раздел','/admin/forumParts/create/',array('class'=>'btn btn-default btn-primary')); ?>&nbsp;
<?php $this->widget('zii.widgets.grid.CGridView',array( // ну да, с бутстраповским TbGridView не совсем удобно, поэтому юзаем стандартный CGridView
'id'=>$table_id.'-grid',
'dataProvider'=>$model->search(),
'summaryText'=>'',
'itemsCssClass' => 'table table-striped table-condensed',
'rowCssClassExpression'=>'"items[]_{$data->part_id} cursor"', // указываем классы для каждой записи. Используется part_id (замените на свой ID-шник)
'columns'=>array(
'part_id',
'part_name',
array(
'class'=>'bootstrap.widgets.TbButtonColumn',
'template' => '{update}{delete}',
),
),
)); ?>

Ну вот почти и все. Осталось лишь сохранить все это дело в контроллере:

    public function actionSort()
{
if (isset($_POST['items']) && is_array($_POST['items'])) {
$i = 0;
foreach ($_POST['items'] as $item) {
$model = ForumParts::model()->findByPk($item);
$model->part_sort = $i;
$model->save();
$i++;
}
}
}

Спасибо за внимание! =)

Защита от XSS уязвимостей

В модели нужно лишь вставить строку, где comm_text и comm_user_name поля, которые могут подвергнуться XSS уязвимости

array('comm_text, comm_user_name','filter','filter'=>array($obj=new CHtmlPurifier(),'purify')),

Кастомная валидация

К примеру нужно из всей модельки проверить на заполнение только 2 поля. В модели в функцию rules добавляем поле:

array('blog_name, blog_text', 'required', 'on' => 'new'),

Где «new» — имя сценария.

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

        if(isset($_GET['id'])){
            $id = intval($_GET['id']);
            $model = Blogs::model()->find('blog_id = '.$id.' AND blog_user_id = '.Yii::app()->user->id);
            if(!$model){
                throw new CHttpException(404,'Запись не найдена.');
            }else{
                $model->scenario = 'new';
            }
        }else{
            $model = new Blogs('new');
        }

 

 

Сортировка записей блога по числу комментариев к статье

Собираем нехитрую конструкцию:


$comm_count_sql = "(SELECT COUNT(*) FROM {{comments}} WHERE comm_item_id = t.blog_id)";

$criteria = new CDbCriteria;
$criteria->with = 'comments';
$criteria->order = 'comm_count DESC';
$criteria->select = array('*', $comm_count_sql . " as comm_count");

$criteria->addCondition('blog_user_id = '.$user->user_id, 'AND');

$dataProvider = new CActiveDataProvider('Blogs', array('criteria' => $criteria, 'pagination'=>array('pageSize'=>10)));

if($dataProvider->getData()){
    $this->widget('zii.widgets.CListView',array(
        'dataProvider'=>$dataProvider,
        'template'=>'{items}{pager}',
        'itemView'=>'_user_items',
        'viewData' => array(
            'user' => $user,
        ),
        'emptyText'=>'',
        'summaryText'=>'',
        'pager'=>array(
            'header'=>'',
            'prevPageLabel'=>'<',
            'nextPageLabel'=>'>',
        ),
    ));
}else{
    echo 'Записей пока нет';
}

В модельке Blogs делаем связку:

    public function relations()
    {
        return array(
            'comments'=>array(self::BELONGS_TO, 'Comments', 'blog_id'),
        );
    }

Вот собственно и все 🙂