Answer the question
In order to leave comments, you need to log in
How to split an array of fields in Model::fields() in yii2 for different cases?
Problem
Suppose there is a REST service represented by two resources: a list of records, information about the record. It is necessary that the list of entries contain only the id and title fields, and the information about the entry: id, title, text, image, author.
How can I solve my problem in the most beautiful way? What do you advise?
How I'm trying to solve this (you don't have to read much below)
I know that I can use the fields get-parameter in the url and list the fields that interest me in it. But I do not like this approach because the url is not as concise as I would like.
Yii2 models have fields() which is used by the serializer in the controller and determines the list of fields to be returned to the client. To separate the list of fields for different usage scenarios, I decided to use the scenario field of the model. This works great exactly until the moment when I use ActiveDataProvider () to which I cannot transfer this script in any way.
In code it looks something like this:
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;
}
}
\Yii::$app->request->setQueryParams(['fields' => 'id, title']);
Answer the question
In order to leave comments, you need to log in
The script can be set, but it looks like this:
$activeDataProvider = new ActiveDataProvider([
'query' => Post::find(),
// 'scenario' => Post::SCENARIO_INDEX, // Это так не работает :(
]);
foreach($activeDataProvider->getModels() as $model) {
$model->scenario = Post::SCENARIO_GUEST;
}
1. I would make 2 models, not scenarios. If there are common methods, you can have a common ancestor. Accordingly, there will be two controllers, each with its own model and there will be no confusion.
2. You can override prepareDataProvider:
https://www.yiiframework.com/doc/api/2.0/yii-rest-...
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question