文档章节

定义多场景的表单

botkenni
 botkenni
发布于 2017/07/30 22:53
字数 719
阅读 11
收藏 0

定义多场景的表单

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

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)这样来判断确定是否要做某些逻辑(当该方法与其它场景共用时)

© 著作权归作者所有

botkenni
粉丝 20
博文 423
码字总数 443612
作品 0
西城
程序员
私信 提问
【中后台应用】从表单抽象到表单中台

从表单抽象到表单中台 作者:jinc 相信前端开发的同学,对表单其实并不陌生,而且时至今日,表单应用的编写因为React、Vue等框架的出现,也变得更加地便捷了。在前端工作中,有着很多中后台应...

FEOne
04/23
0
0
ElementUI多个子组件表单的校验管理

背景 公司项目中所用到的前端框架是Vue.js + ElementUI,因为项目的业务场景中有很多的大表单,但是ElementUI的表单写法对于表单的拆分和校验其实并不是很友好。最初的项目为了方便,常常把多...

李棠辉
03/25
0
0
中后台项目 - 查询表格业务最佳实践

前言 查询表格业务是中后台系统最常用的业务系统之一,我相信该业务场景会在你的项目中会大量出现。既然该此场景在项目中大量的出现,所以对其进行必要的封装会极大的提升业务的复用性以及项...

Tianlikai
04/03
0
0
PostgreSQL 批量导入性能 (采用dblink 异步调用)

标签 PostgreSQL , unlogged table , 批量 , dblink 背景 批量导入数据,怎样能挖掘出系统的比较极限的潜能? 瓶颈通常在哪里? 1、WAL lock 2、INDEX lock 3、EXTEND LOCK 4、autovacuum 干扰...

德哥
2018/05/06
0
0
说说 Vue.js 中的 v-model 指令以及如何绑定表单元素

我们可以使用 Vue.js 中的 v-model 指令来完成表单数据的双向绑定。 1 基础用法 1.1 文本输入框(text) 这里演示了在文本输入框上输入的内容,会实时映射到绑定的数据上。 html: js: 效果...

deniro
2018/12/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

setState() called after dispose() flutter

# 在setState前加入以下判断if (!mounted) return;

zdglf
20分钟前
3
0
docker和docker-compose二种方式安装mysql8.0

Docker方式安装 在命令行下运行 docker run -d -p 3306:3306 --restart always --privileged=true--name mysql-e MYSQL_USER="test" -e MYSQL_PASSWORD="test" -e MYSQL_ROOT_PASSWOR......

小白的成长
29分钟前
5
0
五大网络威胁应对挑战

既然如此,那么威胁的检测和响应过程是否像生产瑞士手表那样高效运行呢?答案远非如此。据ESG报告显示,威胁检测和响应过程充满各种各样的问题。来自372名企业网络安全和IT专家的数据,以下是...

linuxCool
30分钟前
4
0
jQuery 选择器使用大全(标签选择器,ID选择器等)

jQuery的选择器是CSS 1-3,XPath的结合物。jQuery提取这二种查询语言最好的部分,融合后创造出了最终的jQuery表达式查询语言。如果你了解CSS(绝大部分WEB开发者都用到的),那么你学起来就很...

前端老手
36分钟前
4
0
HBase四种部署模式和基本操作

本文主要包括两部分的内容,第一部分主要包HBase的四种安装方法,分别是:① 单机版模式,② 伪集群模式,③ 使用HBase自带的zookeeper构建分布式集群,④ 使用独立安装的zookeeper构建分布式...

繁荣3000
44分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部