Size: a a a

2019 September 08

АС

Антон Ситников in Yii Framework 3
Махмуд
Просмотрел дата ридер. Подскажите правильно ли я понял. Для работы с базой данных надо будет писать свой ридер и переопределять методы ридера, чтоб в зависимости от фильтров и сортировки, подставлять условия в запрос, и в методе read вызывать метод all() в случае использования Актив Рекорд?
для каждого типа базы данных будет свой ридер
источник

М

Махмуд in Yii Framework 3
В случае ArrayDaraReader надо подгружать весь массив данных, чтоб он уже их отфильтровал и отсортировал,  вместо подгрузки необходимого количества данных в данный момент?
источник

AM

Alexander Makarov in Yii Framework 3
Да
источник

AM

Alexander Makarov in Yii Framework 3
Array работает с массивом данных
источник

AM

Alexander Makarov in Yii Framework 3
Другие reader с чем-то другим
источник

М

Махмуд in Yii Framework 3
Alexander Makarov
Array работает с массивом данных
Это я понял. Я о том что подгружать в ридер надо будет  массив с 1000 элементами например, для последующей фильтрации и сортировки, вместо 50-100 нужных на одну страницу пагинации, чтоб не грузить лишние данные.
источник

AM

Alexander Makarov in Yii Framework 3
Ну так это array-ридер. Он ничего не знает о хранилище.
источник

М

Махмуд in Yii Framework 3
Alexander Makarov
Ну так это array-ридер. Он ничего не знает о хранилище.
Спасибо за разъяснение
источник
2019 September 09

PC

Pavel Chaplygin in Yii Framework 3
Вроде круто, но не понял пару моментов. На примере IterableDataReader.
1. Поведение count.
Фильтрация работает, как ожидается - добавляем фильтр, результат read меняется:
$reader = new MyDataReader(...);
$all = $reader->read();
$reader->withFilter(new Like('name', 'agent'));
$totalAgents = $reader->read();
А подсчет так не работает:
$reader = new MyDataReader(...);
$total = count($reader);
$reader->withFilter(new Like('name', 'agent'));
$totalAgents = count($reader);
Тот же OffsetPaginator не будет работать корректно, если передать ему в конструктор IterableDataReader с фильтром.

2. Применение сортировки в том же IterableDataReader.
Сначала limit/offset, а затем сортировка. Контринтуитивно, потому что ожидается (по аналогии с SQL) минимальный и максимальный id  впримере ниже:

$readerMin = (new MyDataReader(...))
   ->withSort((new Sort(['id']))
   ->withOrder(['id' => 'asc']))
   ->withLimit(1);
$readerMax = (new MyDataReader(...))
   ->withSort((new Sort(['id']))
   ->withOrder(['id' => 'desc']))
   ->withLimit(1);
В общем, если я не до конца понял, то ткните меня носом кто-нибудь)
источник

PC

Pavel Chaplygin in Yii Framework 3
Pavel Chaplygin
Вроде круто, но не понял пару моментов. На примере IterableDataReader.
1. Поведение count.
Фильтрация работает, как ожидается - добавляем фильтр, результат read меняется:
$reader = new MyDataReader(...);
$all = $reader->read();
$reader->withFilter(new Like('name', 'agent'));
$totalAgents = $reader->read();
А подсчет так не работает:
$reader = new MyDataReader(...);
$total = count($reader);
$reader->withFilter(new Like('name', 'agent'));
$totalAgents = count($reader);
Тот же OffsetPaginator не будет работать корректно, если передать ему в конструктор IterableDataReader с фильтром.

2. Применение сортировки в том же IterableDataReader.
Сначала limit/offset, а затем сортировка. Контринтуитивно, потому что ожидается (по аналогии с SQL) минимальный и максимальный id  впримере ниже:

$readerMin = (new MyDataReader(...))
   ->withSort((new Sort(['id']))
   ->withOrder(['id' => 'asc']))
   ->withLimit(1);
$readerMax = (new MyDataReader(...))
   ->withSort((new Sort(['id']))
   ->withOrder(['id' => 'desc']))
   ->withLimit(1);
В общем, если я не до конца понял, то ткните меня носом кто-нибудь)
Да, я нашёл https://github.com/yiisoft/data/issues/9, которая наполовину перекрывает мой комментарий. Ну и я своего добавил.
источник

AM

Alexander Makarov in Yii Framework 3
Спасибо
источник

AM

Alexander Makarov in Yii Framework 3
@pchapl отличный код. Вмёржил.
источник

PC

Pavel Chaplygin in Yii Framework 3
Alexander Makarov
@pchapl отличный код. Вмёржил.
Спасибо. Я там ещё сделал реквест по поводу https://github.com/yiisoft/data/issues/7: если отказаться от final в `reader`ах, то кастомные фильтры добавляются довольно легко. В противном случае для расширения какого-то reader придётся копировать весь код и менять нужные методы.
источник

PC

Pavel Chaplygin in Yii Framework 3
А вот особых плюсов от final я не понял
источник

AM

Alexander Makarov in Yii Framework 3
это в случае IterableDataReader выходит так
источник

AM

Alexander Makarov in Yii Framework 3
есть ещё всякие SQLDataReader
источник

PC

Pavel Chaplygin in Yii Framework 3
Я понимаю, что они будут разные, но в чём принципиальное отличие?
Для простого IterableDataReader делаем так:
protected function matchFilter(array $item, array $filter): bool
{
   [$operation, $field] = $filter;

   if ($operation === Digital::getOperator()) {
       return ctype_digit($item[$field]);
   }

   return parent::matchFilter($item, $filter);
}


Для какого-нибудь своего ApiReader другой метод:
protected function buildFilterParam(array $filter): string
{
   [$operation, $field] = $filter;

   if ($operation === Digital::getOperator()) {
       return "{$field}_is_digital=1";
   }

   return parent::buildFilterParam($item, $filter);
}

Для SQLDataReader будет свой метод:
protected function buildCondition($filter, &$params): string
{
   [$operation, $field] = $filter;

   if ($operation === Digital::getOperator()) {
       return $this->escapeField($field) . " ~ '\d+'";
   }

   return parent::buildCondition($item, $filter);
}

В любом случае, реализация собственного фильтра предполагает реализацию построения условий для всех `reader`ов, которые будут использоваться. А с точки зрения `Paginator`ов или `DataProvider`ов ничего не изменится.
источник

PC

Pavel Chaplygin in Yii Framework 3
Наверное, стоит сначала реализовать планируемые DataProvider и FooReader и тогда уже смотреть, можно ли им добавлять свои фильтры.
источник

AM

Alexander Makarov in Yii Framework 3
верно
источник

AM

Alexander Makarov in Yii Framework 3
смёржил
источник