ArrayDataProvider и фильтры в datagrid

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
metsys
Сообщения: 10
Зарегистрирован: 2014.12.17, 17:33

ArrayDataProvider и фильтры в datagrid

Сообщение metsys »

Такая ситуация, есть у меня массив:

Код: Выделить всё

$myArray = [
'0' => ['id' => 0, 'file' => '1.txt', 'stroka' => '2', 'key' => 'aa', 'value' => 'Aab', 'description' => 'Descr of aab'],
'1' => ['id' => 0, 'file' => '1.txt', 'stroka' => '3', 'key' => 'ab', 'value' => 'Aaw', 'description' => 'Descr of aaw'],
] 
Хочется из этого массива сделать GridView - и с этим проблем никаких нету:

Код: Выделить всё

$dataProvider = new ArrayDataProvider([
    'key' => 'id',
    'allModels' => $myArray,
    'sort' => [
        'attributes' => ['id', 'key', 'value', 'description'],
    ],
    'pagination' => [
        'pageSize' => 10,
    ],
        ]);
        
        echo GridView::widget([
    'dataProvider' => $dataProvider,
    //'filterModel' => $search->search(),
    'layout' => "{items}\n{pager}",
    'columns' => [
        'id',
        'key',
        'value',
        'description',
        ],
]); 
Но вот как добавить фильтр в данный GridView что бы производил поиск по данному массиву - понятия не имею. Пробовал уже как то из массива делать набор объектов через \Yii::createObject() и т.п. Ничего не получается. Может кто то подсказать как запилить эти фильтры имея не объект ActiveRecord а вот такой вот массив.

metsys
Сообщения: 10
Зарегистрирован: 2014.12.17, 17:33

Re: ArrayDataProvider и фильтры в datagrid

Сообщение metsys »

Или фильтры в GridView доступны только для ActiveRecord?

Аватара пользователя
Roksalana
Сообщения: 215
Зарегистрирован: 2014.01.14, 09:34

Re: ArrayDataProvider и фильтры в datagrid

Сообщение Roksalana »

Не проверяла, но должно быть так:
'filterModel' => <вызов метода, который обработает данные>

В методе формируем отфильтрованный массив на основе полученные GET параметров (тех самых фильтров, посмотрите как выглядит метод search для моделей ActiveRecord) и возвращаем его в виде ArrayDataProvider.

metsys
Сообщения: 10
Зарегистрирован: 2014.12.17, 17:33

Re: ArrayDataProvider и фильтры в datagrid

Сообщение metsys »

Ну собственно сделал я следующее:

Контроллер:

Код: Выделить всё

$tokens = token_get_all(file_get_contents(dirname(dirname(__DIR__)) . '/frontend/messages/en/common.models.SettingsForm.php'));
        $resultData = [];
        $tDoubleArrow = false;
        foreach ($tokens as $key => $token) {
            if ($token[0] == T_CONSTANT_ENCAPSED_STRING && !$tDoubleArrow) {
                $resultData[$token[2]]['id'] = $token[2];
                $resultData[$token[2]]['key'] = $token[1];
            } else if ($token[0] == T_DOUBLE_ARROW) {
                $tDoubleArrow = true;
            } else if ($token[0] == T_CONSTANT_ENCAPSED_STRING && $tDoubleArrow) {
                $resultData[$token[2]]['value'] = $token[1];
                $tDoubleArrow = false;
            } else if ($token[0] == T_COMMENT) {
                $resultData[$token[2]]['description'] = $token[1];
            }
        }


        $filtersForm = new FiltersForm;
        if (isset($_GET['FiltersForm'])) {
            $filtersForm->filters = $_GET['FiltersForm'];
        }
        $resultData = $filtersForm->filter($resultData);

        return $this->render('about', [
                    'filtersForm' => $filtersForm,
                    'resultData' => $resultData,
        ]);
FiltersForm:

Код: Выделить всё

namespace common\models;

use yii\base\Model;

class FiltersForm extends Model
{
    public $filters = array();

    /**
     * Override magic getter for filters
     */
    public function __get($name)
    {
        if(!array_key_exists($name, $this->filters))
            $this->filters[$name] = null;
        return $this->filters[$name];
    }

    /**
     * Filter input array by key value pairs
     * @param array $data rawData
     * @return array filtered data array
     */
    public function filter(array $data)
    {
        foreach($data AS $rowIndex => $row) {
            foreach($this->filters AS $key => $value) {
                // unset if filter is set, but doesn't match
                if(array_key_exists($key, $row) AND !empty($value)) {
                    if(stripos($row[$key], $value) === false)
                        unset($data[$rowIndex]);
                }
            }
        }
        return $data;
    }
 
}
Вьюха:

Код: Выделить всё

$dataProvider = new ArrayDataProvider([
    'allModels' => $resultData,
    'sort' => [
        'attributes' => ['id', 'key', 'value', 'description'],
    ],
    'pagination' => [
        'pageSize' => 10,
    ],
        ]);

echo GridView::widget([
    'dataProvider' => $dataProvider,
    'filterModel' => $filtersForm,
    'layout' => "{items}\n{pager}",
    'columns' => [
        'id',
        'key',
        'value',
        'description',
    ],
]);
В итоге получаю GridView без фильтров.

Аватара пользователя
Roksalana
Сообщения: 215
Зарегистрирован: 2014.01.14, 09:34

Re: ArrayDataProvider и фильтры в datagrid

Сообщение Roksalana »

Могу конечно ошибаться, но у вашей модели фильтров нет одноименных с DataColumn атрибутом полей, поэтому форма фильтра не строится. Насколько я понимаю: если у Search модели нет поля title, то для этого поля форма фильтра не строится. У вашего фильтра вообще все поля не существуют.
Попробуйте объвить в модели все переменные что и в основной модели
class FiltersForm extends Model
{
public $id, $key ...

Идея в том, что форма фильтра - это форма на основе модели фильтра. Нет полей - нет формы.

Ответить