/**
     * 预载入关联查询 返回模型对象
     * @access public
     * @param Model     $result 数据对象
     * @param string    $relation 关联名
     * @return Model
     */
    public function eagerlyResult($result, $relation)
    {
        return $this->relation()->eagerlyResult($result, $relation);
    }// 提前载入 关联 查询

    /**
     * HAS ONE 关联定义
     * @access public
     * @param string $model 模型名
     * @param string $foreignKey 关联外键
     * @param string $localKey 关联主键
     * @param array  $alias 别名定义
     * @param string $joinType JOIN类型
     * @return Relation
     */
    public function hasOne($model, $foreignKey = '', $localKey = '', $alias = [], $joinType = 'INNER')
    {// 检测关联 定义
        // 记录当前关联信息
        $model      = $this->parseModel($model);// 解析 模型
        $localKey   = $localKey ?: $this->getPk();// 获取主键 完全 是 5.4 以后的语法 了
        $foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';// 获取主键 外键
        return $this->relation()->hasOne($model, $foreignKey, $localKey, $alias, $joinType);// 调用关联 数据库
    }

    /**
     * BELONGS TO 关联定义
     * @access public
     * @param string $model 模型名
     * @param string $foreignKey 关联外键
     * @param string $otherKey 关联主键
     * @param array  $alias 别名定义
     * @param string $joinType JOIN类型
     * @return Relation
     */
    public function belongsTo($model, $foreignKey = '', $otherKey = '', $alias = [], $joinType = 'INNER')
    {// 属于 关联 定义
        // 记录当前关联信息
        $model      = $this->parseModel($model);// 解析 模型
        $foreignKey = $foreignKey ?: Loader::parseName(basename(str_replace('\\', '/', $model))) . '_id';
        $otherKey   = $otherKey ?: (new $model)->getPk();// 主键
        return $this->relation()->belongsTo($model, $foreignKey, $otherKey, $alias, $joinType);// 解析主键
    }

    /**
     * HAS MANY 关联定义
     * @access public
     * @param string $model 模型名
     * @param string $foreignKey 关联外键
     * @param string $localKey 关联主键
     * @param array  $alias 别名定义
     * @return Relation
     */
    public function hasMany($model, $foreignKey = '', $localKey = '', $alias = [])
    {
        // 记录当前关联信息
        $model      = $this->parseModel($model);
        $localKey   = $localKey ?: $this->getPk();
        $foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
        return $this->relation()->hasMany($model, $foreignKey, $localKey, $alias);// 重新封装 成为has many 方向
    }

    /**
     * HAS MANY 远程关联定义
     * @access public
     * @param string $model 模型名
     * @param string $through 中间模型名
     * @param string $foreignKey 关联外键
     * @param string $throughKey 关联外键
     * @param string $localKey 关联主键
     * @param array  $alias 别名定义
     * @return Relation
     */
    public function hasManyThrough($model, $through, $foreignKey = '', $throughKey = '', $localKey = '', $alias = [])
    {// 远程 关联 定义 关联的 外键 跟主键
        // 记录当前关联信息
        $model      = $this->parseModel($model);
        $through    = $this->parseModel($through);
        $localKey   = $localKey ?: $this->getPk();
        $foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
        $name       = Loader::parseName(basename(str_replace('\\', '/', $through)));
        $throughKey = $throughKey ?: $name . '_id';
        return $this->relation()->hasManyThrough($model, $through, $foreignKey, $throughKey, $localKey, $alias);
    }

    /**
     * BELONGS TO MANY 关联定义
     * @access public
     * @param string $model 模型名
     * @param string $table 中间表名
     * @param string $foreignKey 关联外键
     * @param string $localKey 当前模型关联键
     * @param array  $alias 别名定义
     * @return Relation
     */
    public function belongsToMany($model, $table = '', $foreignKey = '', $localKey = '', $alias = [])
    {// 关联定义
        // 记录当前关联信息
        $model      = $this->parseModel($model);
        $name       = Loader::parseName(basename(str_replace('\\', '/', $model)));
        $table      = $table ?: $this->db()->getTable(Loader::parseName($this->name) . '_' . $name);
        $foreignKey = $foreignKey ?: $name . '_id';
        $localKey   = $localKey ?: Loader::parseName($this->name) . '_id';
        return $this->relation()->belongsToMany($model, $table, $foreignKey, $localKey, $alias);
    }

    public function __call($method, $args)
    {// 呼叫 动态 函数调用 未定义的函数,都是这么来的,牛叉
        $query = $this->db();// 首先进行数据库的获取
        // 全局作用域
        if (static::$useGlobalScope && method_exists($this, 'base')) {
            call_user_func_array('static::base', [ & $query]);
        }// 如果是 全局作用域 并且存在 静态的变量
        if (method_exists($this, 'scope' . $method)) {// 如果存在动态的范围扫描
            // 动态调用命名范围
            $method = 'scope' . $method;
            array_unshift($args, $query);// 提出 参数
            call_user_func_array([$this, $method], $args);// 动态调用
            return $this;
        } else {
            return call_user_func_array([$query, $method], $args);// 普通 调用 query 类
        }
    }

    public static function __callStatic($method, $params)
    {
        $model = get_called_class();// 获取当前 类名
        if (!isset(self::$links[$model])) {
            self::$links[$model] = (new static())->db();// 构建 单例的 数据库连接
        }
        $query = self::$links[$model];// 找到 函数
        // 全局作用域
        if (static::$useGlobalScope && method_exists($model, 'base')) {
            call_user_func_array('static::base', [ & $query]);
        }
        return call_user_func_array([$query, $method], $params);// 也是转到 数据库
        // 巧妙的对 静态函数 转换成了 外包的函数
    }

    /**
     * 修改器 设置数据对象的值
     * @access public
     * @param string    $name 名称
     * @param mixed     $value 值
     * @return void
     */
    public function __set($name, $value)
    {
        $this->setAttr($name, $value);
    }// 修改

    /**
     * 获取器 获取数据对象的值
     * @access public
     * @param string $name 名称
     * @return mixed
     */
    public function __get($name)
    {
        return $this->getAttr($name);
    }// 获取数据

    /**
     * 检测数据对象的值
     * @access public
     * @param string $name 名称
     * @return boolean
     */
    public function __isset($name)
    {
        try {
            if (array_key_exists($name, $this->data)) {
                return true;
            } else {
                $this->getAttr($name);
                return true;
            }
        } catch (InvalidArgumentException $e) {
            return false;
        }

    }// 检测存在

    /**
     * 销毁数据对象的值
     * @access public
     * @param string $name 名称
     * @return void
     */
    public function __unset($name)
    {
        unset($this->data[$name]);
    }//销毁

    public function __toString()
    {
        return $this->toJson();
    }// 字符串 就是 转换称为 json

    // JsonSerializable
    public function jsonSerialize()
    {
        return $this->toArray();
    }// 转换 为 数组

    // ArrayAccess
    public function offsetSet($name, $value)
    {
        $this->setAttr($name, $value);
    }// 数组 权限

    public function offsetExists($name)
    {
        return $this->__isset($name);
    }// 偏移量

    public function offsetUnset($name)
    {
        $this->__unset($name);
    }// 偏移量删除

    public function offsetGet($name)
    {
        return $this->getAttr($name);
    }// 偏移量 获取

    /**
     * 解序列化后处理
     */
    public function __wakeup()
    {
        $this->initialize();
    }// 序列化

}