首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >定义多场景的表单

定义多场景的表单

作者头像
botkenni
发布2019-09-02 16:22:42
4150
发布2019-09-02 16:22:42
举报
文章被收录于专栏:IT码农IT码农

定义多场景的表单

下面是一个带有添加/编辑的文章表单示例:

namespace app\forms;

use Yii;
use app\models\Article;

class ArticleForm extends \yii\base\Model{
	const SCENE_ADD = 'add'; //添加场景
	
	const SCENE_EDIT = 'edit'; //编辑场景
	
	public $id = 0; //文章ID,编辑时需要
	
	public $title = ''; //文章标题
	
	public $categoryId = 0; //分类ID
	
	public $content = ''; //文章内容
	
	private $_article = null; //文章实例

	public function rules(){
		return [
			[['id', 'title', 'categoryId', 'content'], 'required'],
			['title', 'string', 'length' => [4, 20]],
			['content', 'string', 'length' => [10, 65535]],
			[['title', 'content'], 'safe'],
			[['id', 'categoryId'], 'integer'],
			['id', 'validateId'],
			['categoryId', 'exist', 'targetClass' => 'app\models\ArticleCategory', 'targetAttribute' => 'id', 'message' => '无效的文章分类'],
		];
	}
	
	//定义不同场景所需要校验的表单属性
	public function scenarios(){
		return [
			//添加,需要标题、分类、内容
			self::SCENE_ADD => ['title', 'categoryId', 'content'],
			
			//编辑,需要ID、标题、内容,没有分类,表示禁止修改分类
			self::SCENE_EDIT => ['id', 'title', 'content'],
		];
	}
	
	public function validateId(){
		$article = Article::findOne($this->id);
		if(!$article){
			$this->addError('id', '无效的文章ID');
			return;
		}
		$this->_article = $article;
	}
	
	public function add(){
		if(!$this->validate()){
			return false;
		}
		
		$article = new Article([
			'title' => $this->title,
			'category_id' => $this->categoryId,
			'content' => $this->content,
			'add_time' => time(),
		]);
		
		if(!$article->save()){
			throw new \yii\base\ErrorException('添加文章失败');
		}
		return $article;
	}
	
	public function edit(){
		if(!$this->validate()){
			return false;
		}
		
		Yii::configure($this->_article, [
			'title' => $this->title,
			'content' => $this->content,
		]);
		if(!$this->_article->save()){
			throw new \yii\base\ErrorException('编辑文章失败');
		}
		return $this->_article;
	}
}

以上表单中,add方法就是添加文章的业务逻辑,edit方法是编辑文章咯,可是两个业务要验证的用户端输入参数都包含了title和content,所以要通过scenarios方法来声明两个场景要校验的属性名称

当执行validate的时候,底层会自动在rules找到相关的规则进行校验,不会对无关的属性规则进行校验

控制器调用示例

public function actionAdd(){
	$form = new ArticleForm([
		'scenario' => ArticleForm::SCENE_ADD,
	]);
	
	//菜鸟注意:如果前端用ActiveForm就别像我这样传第2个参数空字符串
	if(!$form->load(Yii::$app->request->post(), '')){
		return '接收参数失败';
	}
	
	if($article = $form->add()){
		return '添加成功,文章ID是:' . $article->id;
	}else{
		return $form->firstError[0];
	}
}

public function actionEdit(){
	$form = new ArticleForm([
		'scenario' => ArticleForm::SCENE_EDIT,
	]);
	
	//菜鸟注意:如果前端用ActiveForm就别像我这样传第2个参数空字符串
	if(!$form->load(Yii::$app->request->post(), '')){
		return '接收参数失败';
	}
	
	if($form->edit()){
		return '保存完毕';
	}else{
		return $form->firstError[0];
	}
}
如果表单定义了多场景,执行add或edit这些业务处理方法前(其实是validate被执行之前),一定要先设定scenario属性(属性值就是场景的标识)

最终其实就是为了告诉validate要对哪些属性进行validate,而不是盲目地全部validate,毕竟不同场景下有不同的校验字段

深入应用
其实不能仅仅把场景理解为使用在validate控制上的,自己在form里面写的逻辑代码都可以if($this->scenario == self::SCENE_ADD)这样来判断确定是否要做某些逻辑(当该方法与其它场景共用时)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 定义多场景的表单
  • 控制器调用示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档