Yii2 позволяет публиковать только данные из сценария модели

1

У меня есть модель ActiveRecord User с этим методом scenarios():

public function scenarios()
{   
    $scenarios = parent::scenarios();
    $scenarios['create'] = ['username', 'email', 'password']; 
    return $scenarios;
}

Кроме того, эта модель имеет метод rules():

public function rules()
{
    return [
        ['username', 'required', 'on' => ['create']], 
        ['username', 'string', 'min' => 3, 'max' => 55],
        ['email', 'required', 'on' => ['create']],
        ['email', 'email', 'on' => ['create']],
        ['password', 'required', 'on' => ['create']],
        ['password', 'string', 'min' => 6, 'on' => ['create']],
    ];
}

Я хочу отказаться от публикации всех данных с ключами, которые не включены в сценарий "создать" (разрешить получать только данные с ключами: "имя пользователя", "письмо", "пароль").

Сейчас я делаю это в UserController поэтому:

...  
$activeAttributes = $model->activeAttributes();
$postParams = Yii::$app->getRequest()->getBodyParams();

foreach($postParams as $key=>$value){
  if(!(in_array($key, $activeAttributes))) throw new \yii\web\HttpException(404, 'Invalid attribute:' . $key);
}
...

Есть ли более элегантный способ сделать это?

Теги:
yii2

1 ответ

2
Лучший ответ

Я не понимаю, в чем преимущество этого.

Пользователь может публиковать любые данные, но если он строго подтвержден, вам не о чем беспокоиться.

Если вы все же хотите его использовать, ваше решение в порядке, вот несколько замечаний:

  • Для получения данных $_POST используется метод высокого уровня \Yii::$app->request->post() (он может возвращать либо все данные, субаравы, либо определенное значение). getBodyParams() вызывается внутри него.

  • 404 Page Not Found Исключение не подходит для этой ситуации. Я думаю, что 400 Bad Request подходит больше.

  • Лучше использовать встроенные обертки Yii2 для общих исключений, например BadRequestHttpException. Таким образом, вы не беспокоитесь о своем коде и больше думаете о его значении.

  • activeAttributes() возвращает имена атрибутов без значений, поэтому вам не нужно прерывать итерированный элемент в foreach в $key и $value.

Таким образом, код после этих изменений может выглядеть примерно так:

$model = new YourModel(['scenario' => YourModel::SCENARIO_CREATE]);
$activeAttributes = $model->activeAttributes();

foreach (\Yii::$app->requst->post() as $attribute => $value) {
    if (!in_array($attribute, $activeAttributes)) {
        throw new BadRequestHttpException("Invalid attribute: $attribute.");
    }
}
  • 0
    Спасибо за ответ. Я согласен со статусом "400 Bad Request". Это более уместно в этой ситуации. Yii::$app->requst->post() возвращает значения Yii::$app->requst->post() в секции $value , но нам нужно сравнить ключи полученных данных со значениями из activeAttributes ().
  • 0
    @MaximChuprov Да, пропустил это. Исправил ответ.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню