Тема вроде как изжеванна вдоль и поперек, но так как просили больше статьей для новичков, расскажу об интересных особенностях виджета GridView, т.к без него у меня еще не обходился ни один проект. В дальнейшем буду пополнять данный FAQ.
Есть таблица с данными, допустим список пользователей, нужно некоторые из строк выделить другим цветом (например заблоченных юзеров выводить на сером фоне), т.к это куда нагляднее, чем просто надпись «вкл/выкл» в отдельном столбце. И реализуется проще простого: нужно добавить анонимную функцию в атрибут rowOptions
echo GridView::widget([
    'dataProvider' => $data,
    'rowOptions' => function ($model, $key, $index, $grid)
    {
      if($model->is_active == false) {
          return ['style' => 'background-color:#778899;'];
      }
    },
...
])
Т.к в функцию передается $index — текущий номер строки, можно четные строки раскрасить в один цвет, не четные в другой. Точно также можно передать любые параметры, которые попадут в нутрь тега tr. Если же вычислять ничего не нужно, то можно сразу указать массив параметров без анонимной функции
echo GridView::widget([
    'dataProvider' => $data,
    'rowOptions' => ['style' => 'background-color:#778899;'],
...
])
Есть таблица с данными и к примеру нам нужно выводить дату записей с группировкой по месяцам. Январь — дальше строки таблицы за январь. Февраль и тп.Для этого существуют атрибуты beforeRow и afterRow.
Атрибуты beforeRow и afterRow работают по тому же принципу, что и rowOptions за тем исключением, что результат, полученный для этих функций будет выведен до и после тега tr.
$currentDate = date('m');
echo GridView::widget([
    'dataProvider' => $data,
    'beforeRow' =>function ($model, $key, $index, $grid) use ($currentDate)
    {
      if($model->month != $currentDate) {
          return '<tr><td colspan=10>'.$model->month.'</td></tr>';
      }
    }
...
])
Если вы используете ActiveDataProvider, то для решения достаточно понимать, что в query у вас экземпляр класса Query. Это такой не выполненный запрос. ActiveDataProvider добавит к нему limit и offset для постраничного вывода. Но вы может использовать этот запрос и сами, так как вам нужно. Например так:
 $query = MyModel::find()->where(...);
 $data =  new ActiveDataProvider([
            'query' => $query,
        ]);
 $totalSum = $query->sum('amount');
Если у вас используется один контроллер для множества гридов и вам нужно изменить только адрес ссылок для GridView, то сделать это можно передав анонимную функцию в качестве параметра urlCreator. Функция должна возвращать правильно сформированную ссылку:
  ['class' => 'yii\grid\ActionColumn',
   'template' => '{update}   {delete}',
   'urlCreator'=>function($action, $model, $key, $index){
       return \yii\helpers\Url::to(['dashboard/user-'.$action,'id'=>$model->id]);
   }
  ]
Как видно из примера — простой способ изменить порядок кнопок или удалить каку-нибудь из стандартных ({update} {delete} {view}) — это передать параметр template.
Спасибо большое, подстроки как раз мне нужны были). Ещё интересует на уровне новичков тема хранения например pdf файлов с возможностью для пользователей их скачки по временному рандомному пути, который они получат в сообщении.
Самое простое решение:
1) генерим ссылку с параметром, по которому можно понять о каком файле речь и даем ее пользователю как ссылка на скачку
2) по ссылке отдаем заголовки с рандомным именем файла и содержимое оригинального файла
header("Content-type:application/pdf"); header("Content-Disposition:attachment;filename='downloaded.pdf'"); readfile("path/to/original.pdf");Минусы: отсутствие докачки, нагрузка на сервер. Для отдачи статических файлов лучше всего поднять отдельный сервер nginx.
Ещё вспомнил. Как то меня попросили сделать данные в гриде покомпактнее, уменьшить высоту строк и сделать поменьше шрифт. Подскажите, пожалуйста, как лучше это сделать в стандартном гриде в yii2?
Нужно прописать свои CSS-классы или стили. Заставить grid использовать их можно через такие атрибуты как tableOptions, options, captionOptions и тп (см класс yii\grid\GridView)
Т.е будет примерно так:
echo GridView::widget([ 'dataProvider' => $data, 'tableOptions' => ['class' => 'my-table-class'];Добрый день. А возможно ли в GridView сделать так, чтобы колонки были по одним данным, а фильтр по другим. Например табличка с данными по отзывам(отзыв, дата,положительный или отрицательный), а фильтр по пользователям этих отзывов(пол, возраст,…) ?
Или разместить 2 связанных GridView, но в одном убрать фильтр, а в другом как-то скрыть строки, через rowOptions?
Можно. Если фильтровать более чем по 1 полю, то лучше делать форму поиска и результаты выводить в виде GridView (как форму search генерит gii). Если фильтровать столбец по одному параметру, то делаем так
[ 'class' => DataColumn::className(), 'attribute' => 'date', 'filter' => Users::getYears() ],Т.е что происходит:
— метод Users::getYears() возвращает массив возрастов, он будет выпадающим списков сверху в фильтре.
— в search методе нужно обработать это значение. Оно придет как значение аттрибута date
Если массив значений для фильтра не нужен, то параметр filter не добавляем вообще, а просто в search методе обрабатываем значение как нам надо:
// было $query->andFilterWhere(['like', 'date', $this->date]) //станет что-то типа того $query->joinWith('user'); $query->andWhere(['user.age' => $this->date]);Надеюсь смогла объяснить.
Подскажите, пожалуйста, как сделать две таблички.Чтобы при нажатии на любую строчку из первой таблички, например, справа во второй табличке раскрывались подробные характеристики строчки из первой таблицы.
В первой таблице ссылка должна отправлять ajax запрос и отображать результат в том месте где 2-я таблица.
Pjax::begin(); Html::a('Ссылка в качестве значения колонки в первой таблице', $url, [ 'data-pjax' => '#table2']); Pjax::end(); Pjax::begin(['id' => 'table2']); // Начальный текст второй таблицы Pjax::end();В контроллере нужно не забывать делать renderAjax вместо render. Надеюсь стало понятнее в какую сторону смотреть.
По предыдущему вопросу по двум зависимым табличкам.
А можно решить эту проблему с помощью partial view? Без ajax. Подскажите, пожалуйста
Смотрите как это работает: юзер кликнул на ссылку. Вместо того, чтобы перезагружать страницу, отправляем запрос на сервер (ajax) и в ответ получаем кусочек view (renderPartial или renderAjax) только той части, которая нужна для второй таблицы и с помощью JavaScript выводим полученные данные в нужном месте страницы (нужный яваскрипт уже есть в компоненте yii Pjax). Т.е без ajax запроса на сервер не получится.
Но можно сделать и по другому: загружать на страницу сразу всю информацию и скрывать лишнюю в скрытых css дивах. По клику на ссылку с помощью JavaScript нужный див показывается, а все остальные остаются скрытыми.