How do you set a scenario when doing a restful call in Yii2 to return certain fields

时间:2022-10-05 08:55:46

Im currently making a Yii2 RESTful system with AngularJs.

我目前正在使用AngularJs制作Yii2 RESTful系统。

In my database i've got several columns that i want to be able to return when doing a particular call from a certain point in my system.

在我的数据库中,我有几个列,我希望能够从我系统中的某个点进行特定调用时返回。

The problem i'm having is how do i return only a handful of fields eg(id, title and stub) from the restful call in another part of my system so that it ignores other fields in the table.

我遇到的问题是如何从系统另一部分的restful调用中返回少量字段,例如(id,title和stub),以便忽略表中的其他字段。

I would ideally like it to work in a similar way to how a Models rules work with scenarios in yii.

理想情况下,我喜欢它以类似于模型规则如何与yii中的场景一起工作的方式工作。

3 个解决方案

#1


1  

There are two methods, I think:

我认为有两种方法:

1. use params

// returns all fields as declared in fields()
http://localhost/users
// only returns field id and email, provided they are declared in fields()
http://localhost/users?fields=id,email
// returns all fields in fields() and field profile if it is in extraFields()
http://localhost/users?expand=profile
// only returns field id, email and profile, provided they are in fields() and extraFields()
http://localhost/users?fields=id,email&expand=profile

2. overriding model's fields()

// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
    return [
        // field name is the same as the attribute name
        'id',
        // field name is "email", the corresponding attribute name is "email_address"
        'email' => 'email_address',
        // field name is "name", its value is defined by a PHP callback
        'name' => function () {
            return $this->first_name . ' ' . $this->last_name;
        },
    ];
}
// filter out some fields, best used when you want to inherit the parent implementation
// and blacklist some sensitive fields.
public function fields()
{
    $fields = parent::fields();
    // remove fields that contain sensitive information
    unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
    return $fields;
}

more detail, refer to https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md

更多细节,请参阅https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md

#2


0  

You may use scenarios method inside your model for this, but you will have to extend a bit toArray method in order to make it work properly:

您可以在模型中使用scenario方法,但是为了使其正常工作,您必须扩展一点toArray方法:

public function scenarios()
{
    return array_merge(parent::scenarios(), [
        'simple_info' => [
            'email',
            'name',
        ],
        'login' => [
            'id',
            'email',
            'name',
            'auth_token',
        ],
    ]);
}

public function toArray(array $fields = array(), array $expand = array(), $recursive = true)
{
    $scenarios = $this->scenarios();
    $scenario = $this->getScenario();
    if (!empty($scenarios[$scenario])) {
        $data = parent::toArray($fields, $expand, $recursive);
        return array_intersect_key($data, array_flip($scenarios[$scenario]));
    }
    return parent::toArray($fields, $expand, $recursive);
}

After this you may simply do something like this:

在此之后你可能会做这样的事情:

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post(), '') && $model->login()) {
        $user = $model->getUser();
        // Lets change scenario to login in order to get `auth_token` for authorization
        $user->setScenario('login');
        $user->generateAuthKey();
        $user->save(FALSE);
        return $user;
    } else {
        return $model;
    }

#3


0  

As a side note (expanding on the answer from @Ganiks), if you are manually returning the list of Models, you will need to return them as a DataProvider (rather than simply as an array of Models) for the fields parameter to have an effect.

作为旁注(扩展@Ganiks的答案),如果您手动返回模型列表,则需要将它们作为DataProvider(而不是简单地作为模型数组)返回,以使fields参数具有影响。

For example, if you do something like this...

例如,如果你做这样的事......

class UserController extends yii\rest\Controller
{
    public function actionIndex()
    {
        return User::find()->all(); // Not what you want
    }

    // ...
}

... then the fields parameter will not have the desired effect. However, if you instead do this...

...然后fields参数将没有所需的效果。但是,如果你改为这样做......

class UserController extends yii\rest\Controller
{
    public function actionIndex()
    {
        return new ActiveDataProvider([
            'query' => User::find(),
            'pagination' => false,
        ]);
    }

    // ...
}

... then the returned fields will only be those you specified in the fields parameter.

...然后返回的字段将只是您在fields参数中指定的字段。

#1


1  

There are two methods, I think:

我认为有两种方法:

1. use params

// returns all fields as declared in fields()
http://localhost/users
// only returns field id and email, provided they are declared in fields()
http://localhost/users?fields=id,email
// returns all fields in fields() and field profile if it is in extraFields()
http://localhost/users?expand=profile
// only returns field id, email and profile, provided they are in fields() and extraFields()
http://localhost/users?fields=id,email&expand=profile

2. overriding model's fields()

// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
    return [
        // field name is the same as the attribute name
        'id',
        // field name is "email", the corresponding attribute name is "email_address"
        'email' => 'email_address',
        // field name is "name", its value is defined by a PHP callback
        'name' => function () {
            return $this->first_name . ' ' . $this->last_name;
        },
    ];
}
// filter out some fields, best used when you want to inherit the parent implementation
// and blacklist some sensitive fields.
public function fields()
{
    $fields = parent::fields();
    // remove fields that contain sensitive information
    unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);
    return $fields;
}

more detail, refer to https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md

更多细节,请参阅https://github.com/yiisoft/yii2/blob/master/docs/guide/rest-resources.md

#2


0  

You may use scenarios method inside your model for this, but you will have to extend a bit toArray method in order to make it work properly:

您可以在模型中使用scenario方法,但是为了使其正常工作,您必须扩展一点toArray方法:

public function scenarios()
{
    return array_merge(parent::scenarios(), [
        'simple_info' => [
            'email',
            'name',
        ],
        'login' => [
            'id',
            'email',
            'name',
            'auth_token',
        ],
    ]);
}

public function toArray(array $fields = array(), array $expand = array(), $recursive = true)
{
    $scenarios = $this->scenarios();
    $scenario = $this->getScenario();
    if (!empty($scenarios[$scenario])) {
        $data = parent::toArray($fields, $expand, $recursive);
        return array_intersect_key($data, array_flip($scenarios[$scenario]));
    }
    return parent::toArray($fields, $expand, $recursive);
}

After this you may simply do something like this:

在此之后你可能会做这样的事情:

    $model = new LoginForm();
    if ($model->load(Yii::$app->request->post(), '') && $model->login()) {
        $user = $model->getUser();
        // Lets change scenario to login in order to get `auth_token` for authorization
        $user->setScenario('login');
        $user->generateAuthKey();
        $user->save(FALSE);
        return $user;
    } else {
        return $model;
    }

#3


0  

As a side note (expanding on the answer from @Ganiks), if you are manually returning the list of Models, you will need to return them as a DataProvider (rather than simply as an array of Models) for the fields parameter to have an effect.

作为旁注(扩展@Ganiks的答案),如果您手动返回模型列表,则需要将它们作为DataProvider(而不是简单地作为模型数组)返回,以使fields参数具有影响。

For example, if you do something like this...

例如,如果你做这样的事......

class UserController extends yii\rest\Controller
{
    public function actionIndex()
    {
        return User::find()->all(); // Not what you want
    }

    // ...
}

... then the fields parameter will not have the desired effect. However, if you instead do this...

...然后fields参数将没有所需的效果。但是,如果你改为这样做......

class UserController extends yii\rest\Controller
{
    public function actionIndex()
    {
        return new ActiveDataProvider([
            'query' => User::find(),
            'pagination' => false,
        ]);
    }

    // ...
}

... then the returned fields will only be those you specified in the fields parameter.

...然后返回的字段将只是您在fields参数中指定的字段。