Задача
Предположим, есть REST-сервис, представленный двумя ресурсами: список записей, информация о записи. Нужно, чтобы список записей содержал только поля id и title, а информация о записи: id, title, text, image, author.
Как мне решить мою задачу наиболее красивым способом? Что посоветуете?
Как я пытаюсь это решить (ниже можно особо не читать)
Я знаю, что в url могу использовать get-параметр fields и в нем перечислить те поля, что меня интересуют. Но мне такой подход не нравится тем, что url становится не таким лаконичным, как бы мне хотелось.
В моделях Yii2 есть fields(), который используется сериализатором в контроллере и определяет список полей, которые следует вернуть клиенту. Для разделения списка полей для разных сценариев использования я решил воспользоваться полем scenario у модели. Это прекрасно работает ровно до того момента, пока я не использую ActiveDataProvider(), в который никаким способом этот сценарий я передать не могу.
В коде это выглядит как-то так:class Post
{
const SCENARIO_INDEX = 'index';
const SCENARIO_VIEW = 'view';
public function fields()
{
$fields = parent::fields();
if ($this->scenario === self::SCENARIO_INDEX) {
$fields = ['id', 'title'];
}
if ($this->scenario === self::SCENARIO_VIEW) {
$fields = ['id', 'title', 'text', 'image', 'author'];
}
return $fields;
}
}
class PostController extends \yii\rest\Controller
{
public function actionIndex()
{
return new ActiveDataProvider([
'query' => Post::find(),
// 'scenario' => Post::SCENARIO_INDEX, // Это так не работает :(
]);
}
public function actionView($id)
{
$post = Post::findOne((int) $id);
if (!$post) {
throw new NotFoundHttpException();
}
$post->scenario = Post::SCENARIO_VIEW;
return $post;
}
}
На ум мне пришли три решения:
1. Собственная реализация ActiveDataProvider с поддержкой сценариев.
2. Не использовать сценарии. Создать наследников Post (например, PostForIndex, PostForView), в которых переопределять fields() под мои нужды.
3. Не использовать сценарии. В контроллере задать get-параметры:
\Yii::$app->request->setQueryParams(['fields' => 'id, title']);