## Yii2模型中的场景 [TOC]   在不同的场景下,模型可能会使用不同的业务规则和逻辑, 例如`email`属性在注册时强制要求有,但在登陆时不需要;也就是说`User`模型可能会在收集用户登录输入, 也可能会在用户注册时使用验证。   场景特性主要在**验证**、**属性块赋值**或者**基于不同的场景定义不同的 属性标签**。 ### 使用场景进行验证 #### 定义模型验证规则 文件在`app\models\Users.php`内容如下: ```php <?php namespace app\models; use yii\db\ActiveRecord; class Users extends ActiveRecord { const SCENARIO_LOGIN = 'login'; const SCENARIO_REGISTER = 'register'; /** * @return string */ public static function tableName() { return 'users'; } public function rules() { return [ // 在"register" 场景下 username, email 和 password 必须有值 [['username', 'email', 'password'], 'required', 'on' => self::SCENARIO_REGISTER], // 在 "login" 场景下 username 和 password 必须有值 [['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN], ]; } } ``` #### 在控制器中使用 文件在`app\controllers\UserController.php`内容如下: ```php <?php namespace app\controllers; use app\models\Users; use yii\web\Controller; class UserController extends Controller { public function actionLogin() { $model = new Users; $model->scenario = Users::SCENARIO_LOGIN; // 或者通过构造函数配置 $model = new Users(['scenario'=>'login']); if (\Yii::$app->request->isPost) { } return $this->render('login', ['model' => $model]); } public function actionRegister() { $model = new Users(['scenario'=>'register']); if (\Yii::$app->request->isPost) { } return $this->render('login', ['model' => $model]); } } ``` #### 视图文件 文件在`app\views\user\login.php`内容如下: ```html <?php use yii\helpers\Html; use yii\widgets\ActiveForm; ?> <?php $form = ActiveForm::begin(['id' => 'contact-form']); ?> <?= $form->field($model, 'username')->textInput(['autofocus' => true]) ?> <?= $form->field($model, 'email') ?> <?= $form->field($model, 'password')->passwordInput() ?> <div class="form-group"> <?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?> </div> <?php ActiveForm::end(); ?> ``` #### 访问预览 ![](https://box.kancloud.cn/898ad73c868acd446f765ff8a901539a_1223x446.png) > 不同的控制器调用不同的**模型场景**,对数据进行校验。 ### 使用场景进行属性块赋值   使用场景进行属性块赋值只是在赋值给模块的`attributes`属性赋值的时候会根据定义的规则进行赋值。 #### 定义模型场景规则 文件在`app\models\Users.php`内容如下: ```php <?php namespace app\models; use yii\db\ActiveRecord; class Users extends ActiveRecord { const SCENARIO_LOGIN = 'login'; const SCENARIO_REGISTER = 'register'; /** * @return string */ public static function tableName() { return 'users'; } /** * @return array */ public function scenarios() { $scenarios = parent::scenarios(); $scenarios[self::SCENARIO_LOGIN] = ['username', 'password']; $scenarios[self::SCENARIO_REGISTER] = ['username', 'email', 'password']; return $scenarios; } } ``` #### 控制器代码 ```php <?php namespace app\controllers; use app\models\Users; use yii\web\Controller; class UserController extends Controller { public function actionLogin() { $model = new Users; $model->scenario = Users::SCENARIO_LOGIN; // 或者通过构造函数配置 $model = new Users(['scenario'=>'login']); if (\Yii::$app->request->isPost) { $model->attributes = \Yii::$app->request->post('Users'); print_r($model); // 查看model的属性只有"username"和"password"被赋值 } return $this->render('login', ['model' => $model]); } public function actionRegister() { $model = new Users(['scenario'=>'register']); if (\Yii::$app->request->isPost) { $model->attributes = \Yii::$app->request->post('Users'); print_r($model);// 查看model的属性只有"username","email"和"password"被赋值 } return $this->render('login', ['model' => $model]); } } ``` #### 查看视图结果 ![](https://box.kancloud.cn/4af648836112abbfd1b8112695e4fec4_1269x226.png) > 访问`login()`操作,得到的是模型中定义的`login`场景限制的字段'username', 'password'。 访问`register()`操作,得到的是模型中定义的`register`场景限制的字段'username', 'email', 'password'。 ### 使用场景定义不同的属性标签   属性标签是 视图一部分,但是在模型中申明标签通常非常方便, 并可形成非常简洁可重用代码。 #### 定义模型规则 文件在`app\models\Users.php`内容如下(主要查看`attributeLabels()`方法): ```php <?php namespace app\models; use yii\db\ActiveRecord; class Users extends ActiveRecord { const SCENARIO_LOGIN = 'login'; const SCENARIO_REGISTER = 'register'; /** * @return string */ public static function tableName() { return 'users'; } /** * @return array */ public function attributeLabels() { if ($this->scenario == self::SCENARIO_LOGIN) { $typeString = '登录'; $userName = $typeString . '用户名'; $email = $typeString . '邮箱'; $password = $typeString . '密码'; } else { $typeString = '注册'; $userName = $typeString . '名'; $email = $typeString . '邮箱'; $password = $typeString . '密码'; } return [ 'username' => $userName, 'email' => $email, 'password' => $password, ]; } } ``` #### 控制器使用`render()`方法渲染模板文件 ```php <?php namespace app\controllers; use yii\web\Controller; class UserController extends Controller { public function actionLogin() { return $this->render('login', ['model' => $model]); } public function actionRegister() { return $this->render('login', ['model' => $model]); } } ``` #### 查看效果 ![](https://box.kancloud.cn/e4b9be880bb6c5c785291575e64bc8b7_1594x382.png) > 访问`register()`操作和`login()`操作相应的提示字段变成自定义的。