Rest поиск\фильтрация

Всё что касается построения API
Ответить
n.osenni
Сообщения: 14
Зарегистрирован: 2017.08.17, 01:19

Rest поиск\фильтрация

Сообщение n.osenni » 2018.02.10, 00:15

Пробую сделать поиск\фильтрацию по переданным через url параметрам. Например, http://db5b/web/label-samples?sample_id=2. Запрос к модели LabelSample

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

 * @property int $id
 * @property int $sample_id
 * @property int $label_id
В контроллер, если я правильно понял, добавляю actions()

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

<?php

namespace app\controllers;

use app\models\LabelSample;

class LabelSampleController extends BaseController
{
    public $modelClass = 'app\models\LabelSample';

    public function actions()
    {
        return [
            'index' => [
                'class' => 'yii\rest\IndexAction',
                'modelClass' => $this->modelClass,
                'prepareDataProvider' => function () {
                    $searchModel = new LabelSample();
                    return $searchModel->search(\Yii::$app->request->queryParams);
                },
            ],
        ];
    }
}
А в модель (сгенерирована с помощью gii) следует добавить метод search(). И вот тут у меня загвоздка - как его правильно описать\написать? Мой вариант, представленный ниже, возвращает ошибки валидации, даже если указанные в ошибке параметры переданы:

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

public function search($params)
{
    $query = LabelSample::find();
    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    $this->load($params);
    if (!$this->validate()) {
        print_r($this->errors);
        $query->where('0=1');
        return $dataProvider;
    }

    $query->andFilterWhere([
        'sample_id' => $this->sample_id,
    ]);

    return $dataProvider;
}
Ошибка
Array
(
[sample_id] => Array
(
[0] => Sample ID cannot be blank.
)

[label_id] => Array
(
[0] => Label ID cannot be blank.
)

)
[]

Аватара пользователя
ElisDN
Сообщения: 4836
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Rest поиск\фильтрация

Сообщение ElisDN » 2018.02.10, 06:38

$this->load($params, ‘’);

n.osenni
Сообщения: 14
Зарегистрирован: 2017.08.17, 01:19

Re: Rest поиск\фильтрация

Сообщение n.osenni » 2018.02.10, 11:47

ElisDN писал(а):
2018.02.10, 06:38
$this->load($params, ‘’);
Спасибо за ответ! Сделал так, и действительно - стало лучше. Если запрос http://db5b/web/label-samples?sample_id=2 , то уже не просит ввести sample_id, как раньше, но просит ввести label_id. В модели в правилах эти два поля required, но разве это не исключительно для добавления новых данных через модель? Как быть?

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

public function rules()
    {
        return [
            [['sample_id', 'label_id'], 'required'],
            [['sample_id', 'label_id'], 'integer'],
            [['sample_id', 'label_id'], 'unique', 'targetAttribute' => ['sample_id', 'label_id']],
            [['label_id'], 'exist', 'skipOnError' => true, 'targetClass' => Label::className(), 'targetAttribute' => ['label_id' => 'id']],
            [['sample_id'], 'exist', 'skipOnError' => true, 'targetClass' => Sample::className(), 'targetAttribute' => ['sample_id' => 'id']],
        ];
    }
текущая ошибка при запросе http://db5b/web/label-samples?sample_id=2
Array
(
[label_id] => Array
(
[0] => Label ID cannot be blank.
)

)
[]

Аватара пользователя
ElisDN
Сообщения: 4836
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Rest поиск\фильтрация

Сообщение ElisDN » 2018.02.10, 13:42

В LabelSampleSearch должны быть свои rules() без 'required'.

n.osenni
Сообщения: 14
Зарегистрирован: 2017.08.17, 01:19

Re: Rest поиск\фильтрация

Сообщение n.osenni » 2018.02.10, 14:13

ElisDN писал(а):
2018.02.10, 13:42
В LabelSampleSearch должны быть свои rules() без 'required'.
Получается, что если я хочу сделать фильтрацию\поиск по какой-то модели, нужно в контроллере код нагородить, создать отдельную модель, там ещё нагородить код и т.п.?

Чем же это тогда удобнее создания в контроллере экшена с подготовленным запросом, который будет осуществлять поиск по БД? Экшн этот всего лишь нужно в конфиге зарегистрировать - одну строку добавить.

Аватара пользователя
ElisDN
Сообщения: 4836
Зарегистрирован: 2012.10.07, 10:24
Контактная информация:

Re: Rest поиск\фильтрация

Сообщение ElisDN » 2018.02.10, 14:39

При генерации CRUD в Gii он сам подставляет rules(). Вручную городить не придётся.

n.osenni
Сообщения: 14
Зарегистрирован: 2017.08.17, 01:19

Re: Rest поиск\фильтрация

Сообщение n.osenni » 2018.02.10, 14:45

ElisDN писал(а):
2018.02.10, 14:39
При генерации CRUD в Gii он сам подставляет rules(). Вручную городить не придётся.
Это понятно, но просто при использовании dataProvider нужно создать отдельную модель, добавить туда ещё кучу строк кода. И в самом контроллере ещё нужно добавить много строк. И выходит, что так нужно делать для каждой модели-контроллера, где есть нужна сделать фильтрацию.

Или же можно в контроллере добавить экшн с поиском по модели. И добавить в конфиг пару строк. И не нужно создавать модель, в модели настраивать поиск, в контроллере настраивать провайдер. Или это ошибочный подход?

Solo.dmitry
Сообщения: 2
Зарегистрирован: 2018.02.13, 09:50

Re: Rest поиск\фильтрация

Сообщение Solo.dmitry » 2018.02.13, 10:02

Тоже столкнулся с этой проблемой. Нигде не могу найти целостного решения. Вы на чем остановились?

Solo.dmitry
Сообщения: 2
Зарегистрирован: 2018.02.13, 09:50

Re: Rest поиск\фильтрация

Сообщение Solo.dmitry » 2018.02.14, 13:28

Покажите, пожалуйста, как вызывать REST с фильтром, включающим условия с null-значениями, операторами больше-меньше и тп.

Я не могу понять как вызывать функциональность, реализованную в ActiveDataProvider

Ответить