ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

tp5 model 保存数据及验证

2021-05-12 14:02:57  阅读:172  来源: 互联网

标签:验证 type rule tp5 result key model data isset


model源码

public function save($data = [], $where = [], $sequence = null) {

		if (!empty($data)) {
			// 数据自动验证
			if (!$this->validateData($data)) {
				return false;
			}
			// 数据对象赋值
			foreach ($data as $key => $value) {
				$this->setAttr($key, $value, $data);
			}
			if (!empty($where)) {
				$this->isUpdate = true;
			}
		}

		// 自动关联写入
		if (!empty($this->relationWrite)) {
			$relation = [];
			foreach ($this->relationWrite as $key => $name) {
				if (is_array($name)) {
					if (key($name) === 0) {
						$relation[$key] = [];
						foreach ($name as $val) {
							if (isset($this->data[$val])) {
								$relation[$key][$val] = $this->data[$val];
								unset($this->data[$val]);
							}
						}
					} else {
						$relation[$key] = $name;
					}
				} elseif (isset($this->relation[$name])) {
					$relation[$name] = $this->relation[$name];
				} elseif (isset($this->data[$name])) {
					$relation[$name] = $this->data[$name];
					unset($this->data[$name]);
				}
			}
		}
		// 数据自动完成
		$this->autoCompleteData($this->auto);
		// 事件回调
		if (false === $this->trigger('before_write', $this)) {
			return false;
		}
		$pk = $this->getPk();
		if ($this->isUpdate) {
			// 检测字段
			$this->checkAllowField($this->data, array_merge($this->auto, $this->update));

			// 自动更新
			$this->autoCompleteData($this->update);

			// 获取有更新的数据
			$data = $this->getChangedData();

			// 事件回调
			if (false === $this->trigger('before_update', $this)) {
				return false;
			}

			if (empty($data) || (count($data) == 1 && is_string($pk) && isset($data[$pk]))) {
				// 关联更新
				if (isset($relation)) {
					$this->autoRelationUpdate($relation);
				}
				return 0;
			} elseif ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
				// 自动写入更新时间
				$data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
			}

			if (empty($where) && !empty($this->updateWhere)) {
				$where = $this->updateWhere;
			}

			// 保留主键数据
			foreach ($this->data as $key => $val) {
				if ($this->isPk($key)) {
					$data[$key] = $val;
				}
			}

			if (is_string($pk) && isset($data[$pk])) {
				if (!isset($where[$pk])) {
					unset($where);
					$where[$pk] = $data[$pk];
				}
				unset($data[$pk]);
			}

			// 模型更新
			$result = $this->getQuery()->where($where)->update($data);

			// 关联更新
			if (isset($relation)) {
				$this->autoRelationUpdate($relation);
			}

			// 更新回调
			$this->trigger('after_update', $this);

		} else {
			// 检测字段
			$this->checkAllowField($this->data, array_merge($this->auto, $this->insert));

			// 自动写入
			$this->autoCompleteData($this->insert);

			// 自动写入创建时间和更新时间
			if ($this->autoWriteTimestamp) {
				if ($this->createTime && !isset($this->data[$this->createTime])) {
					$this->data[$this->createTime] = $this->autoWriteTimestamp($this->createTime);
				}
				if ($this->updateTime && !isset($this->data[$this->updateTime])) {
					$this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
				}
			}

			if (false === $this->trigger('before_insert', $this)) {
				return false;
			}

			$result = $this->getQuery()->insert($this->data);

			// 获取自动增长主键
			if ($result && is_string($pk) && (!isset($this->data[$pk]) || '' == $this->data[$pk])) {
				$insertId = $this->getQuery()->getLastInsID($sequence);
				if ($insertId) {
					$this->data[$pk] = $insertId;
				}
			}

			// 关联写入
			if (isset($relation)) {
				foreach ($relation as $name => $val) {
					$method = Loader::parseName($name, 1, false);
					$this->$method()->save($val);
				}
			}

			// 标记为更新
			$this->isUpdate = true;

			// 新增回调
			$this->trigger('after_insert', $this);
		}
		// 写入回调
		$this->trigger('after_write', $this);

		// 重新记录原始数据
		$this->origin = $this->data;

		return $result;
	}

传入data不为空 执行顺序:验证 赋值 关联数据 自动补全 更新或保存数据

传入data为空 执行顺序:关联数据 自动补全 更新或保存数据

即 先验证后补全数据 ,若有需要根据表单其他数据做验证并且设置值的,应该是先验证后赋值。

比如判断传入文件的扩展名,并根据判断补全数据库一个字段,应先验证,再model赋值,两边部分代码会重复。

validate源码

protected function checkItem($field, $value, $rules, $data, $title = '', $msg = []) {
		// 支持多规则验证 require|in:a,b,c|... 或者 ['require','in'=>'a,b,c',...]
		if (is_string($rules)) {
			$rules = explode('|', $rules);
		}
		$i = 0;
		foreach ($rules as $key => $rule) {
			if ($rule instanceof \Closure) {
				$result = call_user_func_array($rule, [$value, $data]);
				$info = is_numeric($key) ? '' : $key;
			} else {
				// 判断验证类型
				if (is_numeric($key)) {
					if (strpos($rule, ':')) {
						list($type, $rule) = explode(':', $rule, 2);
						if (isset($this->alias[$type])) {
							// 判断别名
							$type = $this->alias[$type];
						}
						$info = $type;
					} elseif (method_exists($this, $rule)) {
						$type = $rule;
						$info = $rule;
						$rule = '';
					} else {
						$type = 'is';
						$info = $rule;
					}
				} else {
					$info = $type = $key;
				}

				// 如果不是require 有数据才会行验证
				if (0 === strpos($info, 'require') || (!is_null($value) && '' !== $value)) {
					// 验证类型
					$callback = isset(self::$type[$type]) ? self::$type[$type] : [$this, $type];

					// 验证数据
					$result = call_user_func_array($callback, [$value, $rule, $data, $field, $title]);
				} else {
					$result = true;
				}
			}

			if (false === $result) {
				// 验证失败 返回错误信息
				if (isset($msg[$i])) {
					$message = $msg[$i];
					if (is_string($message) && strpos($message, '{%') === 0) {
						$message = Lang::get(substr($message, 2, -1));
					}
				} else {
					$message = $this->getRuleMsg($field, $title, $info, $rule);
				}
				return $message;
			} elseif (true !== $result) {
				// 返回自定义错误信息
				if (is_string($result) && false !== strpos($result, ':')) {
					$result = str_replace([':attribute', ':rule'], [$title, (string) $rule], $result);
				}
				return $result;
			}
			$i++;
		}
		return $result;
	}

这个checkItem是验证数据,被同一个类里具有public访问权限的check方法调用。

没有设置require规则的字段,验证其他规则的情况为非空不验证。

call_user_func_array($callback, [$value, $rule, $data, $field, $title]); 这句调用对应验证方法。

对于自定义的验证规则来说应该可以写成这样:'type' => 'require|checkType',而不是这样:'type' => 'require|checkType:', 即自定义方法后面可以不必用“:”结尾,还没测试过。

check方法中,对于其错误信息直接赋值给$this->error,model也是直接赋值给$this->error,并且model和validate都有一个getError方法,也都是直接返回$this->error。

标签:验证,type,rule,tp5,result,key,model,data,isset
来源: https://blog.csdn.net/lsswear/article/details/116704712

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有