/**
 * 设置允许写入的字段
 * @access public
 * @param bool|array $field 允许写入的字段 如果为true只允许写入数据表字段
 * @return $this
 */
public function allowField($field)
{// 关于数据库的操作,设置许可字段
    if (true === $field) {// 如果字段为 true
        $field = $this->db()->getTableInfo('', 'type');// 获取 表字段  信息
        $this->db()->setFieldType($field);// 设置 字段类型
        $field = array_keys($field);// 返回 字段信息
    }
    $this->field = $field;// 否则 获取字段 设置字段信息到当前模型
    return $this;// 返回对象本身
}

/**
 * 是否为更新数据
 * @access public
 * @param bool  $update
 * @param mixed $where
 * @return $this
 */
public function isUpdate($update = true, $where = null)
{// 是否为 更新 数据
    $this->isUpdate = $update;// 默认 是 true
    if (!empty($where)) {
        $this->updateWhere = $where; // 如果没有 条件 就不是更新语句
    }
    return $this;// 返回对象本身
}

/**
 * 数据自动完成
 * @access public
 * @param array $auto 要自动更新的字段列表
 * @return void
 */
protected function autoCompleteData($auto = [])
{// 数据自动完成 自动完成数据传入
    foreach ($auto as $field => $value) {// 循环
        if (is_integer($field)) {// 如果字段是整型
            $field = $value;// 赋值字段 过来
            $value = null;// 赋值为空
        }
        if (!in_array($field, $this->change)) {// 如果字段 在改变范围内,使用改变函数 设置
            $this->setAttr($field, !is_null($value) ? $value : (isset($this->data[$field]) ? $this->data[$field] : $value));
        }
    }
}

/**
 * 删除当前的记录
 * @access public
 * @return integer
 */
public function delete()
{// 分别形成了,对 db 的二次 包装
    if (false === $this->trigger('before_delete', $this)) {// 启动之前的东西
        return false;
    }

    $result = $this->db()->delete($this->data);// 删除

    $this->trigger('after_delete', $this);// 删除之后的东西
    return $result;// 返回删除结果
}

/**
 * 设置自动完成的字段( 规则通过修改器定义)
 * @access public
 * @param array $fields 需要自动完成的字段
 * @return $this
 */
public function auto($fields)// 自动完成 字段
{
    $this->auto = $fields;// 字段 自动完成的 字段
    return $this;
}

/**
 * 设置字段验证
 * @access public
 * @param array|string|bool $rule 验证规则 true表示自动读取验证器类
 * @param array             $msg 提示信息
 * @return $this
 */
public function validate($rule = true, $msg = [])// 设置字段 验证
{
    if (is_array($rule)) {// 设置 自动完成的规则
        $this->validate = [
            'rule' => $rule,
            'msg'  => $msg,
        ];
    } else {
        $this->validate = true === $rule ? $this->name : $rule;// 自动完成 字段
    }
    return $this;
}

/**
 * 设置验证失败后是否抛出异常
 * @access public
 * @param bool $fail 是否抛出异常
 * @return $this
 */
public function validateFailException($fail = true)
{
    $this->failException = $fail;// 是否 异常 抛出
    return $this;
}

/**
 * 自动验证数据
 * @access protected
 * @param array $data 验证数据
 * @return bool
 */
protected function validateData($data)// 自动验证数据
{
    if (!empty($this->validate)) {// 如果规则为空 直接飘过,否则
        $info = $this->validate;// 获取信息
        if (is_array($info)) {// 数组
            $validate = Loader::validate();// 加载自动验证类
            $validate->rule($info['rule']);// 设置规则
            $validate->message($info['msg']);// 设置信息
        } else {
            $name = is_string($info) ? $info : $this->name;//单字段 验证,
            if (strpos($name, '.')) {
                list($name, $scene) = explode('.', $name);
            }
            $validate = Loader::validate($name);
            if (!empty($scene)) {
                $validate->scene($scene);// 特殊的处理用法
            }
        }
        if (!$validate->check($data)) {// 数据效验 结果
            $this->error = $validate->getError();// 没通过效验的错误信息
            if ($this->failException) {// 如果允许抛出异常,抛出异常
                throw new ValidateException($this->error);
            } else {
                return false;
            }
        }
        $this->validate = null;// 清空 验证规则
    }
    return true;
}

/**
 * 返回模型的错误信息
 * @access public
 * @return string
 */
public function getError()// 返回错误信息
{
    return $this->error;
}

/**
 * 注册回调方法
 * @access public
 * @param string        $event 事件名
 * @param callable      $callback 回调方法
 * @param bool          $override 是否覆盖
 * @return void
 */
public static function event($event, $callback, $override = false)
{
    $class = get_called_class();// 获取回调类
    if ($override) {
        self::$event[$class][$event] = [];
    }
    self::$event[$class][$event][] = $callback;// 事件回调方法
}

/**
 * 触发事件
 * @access protected
 * @param string    $event 事件名
 * @param mixed     $params 传入参数(引用)
 * @return bool
 */
protected function trigger($event, &$params)// 触发相应的事件
{
    if (isset(self::$event[$this->class][$event])) {// 获取类对应的 时间 函数
        foreach (self::$event[$this->class][$event] as $callback) {
            if (is_callable($callback)) {// 可以调用
                $result = call_user_func_array($callback, [ & $params]);// 调用结果
                if (false === $result) {
                    return false;// 如果其中一个终止了这个事情,停止继续执行
                }
            }
        }
    }
    return true;
}

/**
 * 写入数据
 * @access public
 * @param array     $data 数据数组
 * @return $this
 */
public static function create($data = [])
{
    $model = new static();
    $model->isUpdate(false)->save($data, []);// 进行数据写入,通过model 写入,还是很厉害啊
    return $model;
}

/**
 * 更新数据
 * @access public
 * @param array     $data 数据数组
 * @param array     $where 更新条件
 * @return $this
 */
public static function update($data = [], $where = [])
{
    $model  = new static();
    $result = $model->isUpdate(true)->save($data, $where);// 数据 条件
    return $model;
}

/**
 * 查找单条记录
 * @access public
 * @param mixed        $data  主键值或者查询条件(闭包)
 * @param array|string $with  关联预查询
 * @param bool         $cache 是否缓存
 * @return static
 * @throws exception\DbException
 */
public static function get($data = null, $with = [], $cache = false)
{
    $query = static::parseQuery($data, $with, $cache);
    return $query->find($data);//单条记录
}

/**
 * 查找所有记录
 * @access public
 * @param mixed        $data  主键列表或者查询条件(闭包)
 * @param array|string $with  关联预查询
 * @param bool         $cache 是否缓存
 * @return static[]|false
 * @throws exception\DbException
 */
public static function all($data = null, $with = [], $cache = false)
{
    $query = static::parseQuery($data, $with, $cache);
    return $query->select($data);// 多条数据
}