Как создать сценарий в Yii2 без активных правил проверки?

У меня есть модель MyEntity.php. В рамках скрипта модели определены некоторые правила и некоторые сценарии:

public function rules()
{
    return [
        [['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required'],
        [['myentity_id'], 'integer'],
        [['myentity_title', 'myentity_content'], 'string', 'max' => 120],
        [['myentity_date'], 'safe'],            
    ];
}

public function scenarios()
{
    $scenarios = parent::scenarios();
    $scenarios['scenario_one'] = ['myentity_id', 'myentity_title'];
    $scenarios['scenario_two'] = ['myentity_id', 'myentity_content'];
    return $scenarios;
}

Мне нужно иметь возможность иметь разные сценарии, и для разных действий должны быть активны только определенные проверки (по параметрам). Например, scene_one для actionOne, scene_two для actionTwo и т. Д.

Вот небольшая часть кода из контроллера:

public function actionOne($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_one';
    .
    .
    .
}

public function actionTwo($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_two';
    .
    .
    .
}

Теперь я хочу иметь сценарий_три, где вообще не должно быть никаких проверок. У меня будут дополнительные проверки в коде, которые предотвратят сбой при сохранении в базе данных. Мне просто нужно убедиться, что никакие проверки не применяются, потому что это препятствует отправке моей формы. Если я не применяю какой-либо сценарий, то применяется сценарий по умолчанию (все перечисленные проверки будут активными, что полностью противоположно сценарию, который мне нужен).

2 ответа

Решение

Чтобы сделать это, вам нужно сделать несколько вещей (включая те, которые вы почти сделали сами):

  • В вашем контроллере напишите $modelMyEntity->scenario = 'scenario_three';

  • В модели добавьте дополнительный массив сценариев scenarios() метод:

Как это:

$scenarios['scenario_three'] = ['myentity_id', 'myentity_content'];
  • Наконец, большинство изменений потребуются в rules() так как вам нужно будет добавить, куда включить или исключить конкретные сценарии.

В принципе, в каждом правиле вы можете написать except условно и укажите, какие атрибуты не будут соответствовать какому сценарию. Итак, в вашем примере, скажем, давайте исключим все атрибуты для scenario_three:

[['myentity_id', 'myentity_title', 'myentity_content', 'myentity_date'], 'required', 'except' => 'scenario_three'],
[['myentity_id'], 'integer', 'except' => 'scenario_three'],
[['myentity_title', 'myentity_content'], 'string', 'max' => 120, 'except' => 'scenario_three'],
[['myentity_date'], 'safe'],

Это немного другое решение для того, чтобы игнорировать правила, но я считаю это более привлекательным, потому что в будущем будет проще добавлять / удалять определенные атрибуты для этого сценария, а также будет проще для других разработчиков (если их будет больше, чем только вас) чтобы понять, что вы пытаетесь сделать.

Но я думаю, что решение @ iStranger тоже работает (намного проще).

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

public function actionThree($id)
{           
    $modelMyEntity = $this->findModel($id);
    $modelMyEntity->scenario = 'scenario_three';
    .
    .
    .
}

UPD: Однако я настоятельно рекомендую четко определить все сценарии и соответствующие активные атрибуты (в scenario метод) и удалить $scenarios = parent::scenarios();, потому что это может вызвать ненужные эффекты. Родительская реализация в основном разработана для обратной совместимости с Yii1, которая не имеет scenarios() методы. И это обычно предполагается, если вы переопределите scenarios() метод, вы не должны объединять ваши явно определенные сценарии с родительской реализацией.

Другие вопросы по тегам