tp5源码分析之模型

【QNX+Android虚拟化方案】44 - QNX侧 TouchScreen Panel (TP)触摸屏 Bringup 流程 及 源码分析 阅读详情

1 数据模型

数据模型(Model) 主要实现对单个数据表的操作,包括

数据表整体操作
数据表字段操作
数据表的数据操作

1-1 数据模型的创建

Model->__construct()

数据模型的构造函数,创建数据模型对象

public function __construct($data = [])
    {
        if (is_object($data)) {
            $this->data = get_object_vars($data);
        } else {
            $this->data = $data;
        }

        // 当前类名
        $this->class = get_class($this);

        if (empty($this->name)) {
            // 当前模型名
            $this->name = basename(str_replace('\\', '/', $this->class));
        }

        if (is_null($this->autoWriteTimestamp)) {
            // 自动写入时间戳
            $this->autoWriteTimestamp = $this->db()->getConfig('auto_timestamp');
        }

        // 执行初始化操作
        $this->initialize();
    }

$model->initialize()

模型的初始化操作,使用标志位确保只进行一次初始化

protected function initialize()
    {
        $class = get_class($this);
        if (!isset(static::$initialized[$class])) {
            static::$initialized[$class] = true;
            static::init();
        }
    }

Model::init()

数据表模型的初始化接口

protected static function init()
    {}

1-2 数据库的连接

$model->db()

数据库连接 ,建立模型使用的数据库连接对象

public function db()
    {
        $model = $this->class;
        
        if (!isset(self::$links[$model])) {
            // 设置当前模型 确保查询返回模型对象
            $query = Db::connect($this->connection)->model($model);

            // 设置当前数据表和模型名
            if (!empty($this->table)) {
                $query->setTable($this->table);
            } else {
                $query->name($this->name);
            }

            if (!empty($this->field)) {
                if (true === $this->field) {
                    $type = $query->getTableInfo('', 'type');
                } else {
                    $type = [];
                    foreach ((array) $this->field as $key => $val) {
                        if (is_int($key)) {
                            $key = $val;
                            $val = 'varchar';
                        }
                        $type[$key] = $val;
                    }
                }
                $query->setFieldType($type);
                $this->field = array_keys($type);
                $query->allowField($this->field);
            }

            if (!empty($this->pk)) {
                $query->pk($this->pk);
            }

            self::$links[$model] = $query;
        }
        // 返回当前模型的数据库查询对象
        return self::$links[$model];
    }

2 数据表操作

2-1数据表主键操作

$model->getPk()

获取模型对应数据表的主键

public function getPk($name = '')
    {
        if (!empty($name)) {
            $table = $this->db()->getTable($name);
            return $this->db()->getPk($table);
        } elseif (empty($this->pk)) {
            $this->pk = $this->db()->getPk();
        }
        return $this->pk;
    }

$model->isPk()

判断一个字段是否为数据表的主键

protected function isPk($key)
    {
        $pk = $this->getPk();
        if (is_string($pk) && $pk == $key) {
            return true;
        } elseif (is_array($pk) && in_array($key, $pk)) {
            return true;
        }
        return false;
    }

3 数据表字段操作

3-1 字段的输出控制

$model->hidden()

设置隐藏输出的字段

public function hidden($hidden = [])
    {
        $this->hidden = $hidden;
        return $this;
    }

$model->visible()

设置需要输出的字段

public function visible($visible = [])
    {
        $this->visible = $visible;
        return $this;
    }

$model->append()

设置追加输出的字段

 public function append($append = [])
    {
        $this->append = $append;
        return $this;
    }

3-2 字段的写入操作

$model->allowField()

设置允许写入的字段

public function allowField($field)
    {
        if (true === $field) {
            $field = $this->db()->getTableInfo('', 'type');
            $this->db()->setFieldType($field);
            $field = array_keys($field);
        }
        $this->field = $field;
        return $this;
    }

$model->auto()

设置自动完成的字段

public function auto($fields)
    {
        $this->auto = $fields;
        return $this;
    }

$model->validate()

设置需要验证的字段

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;
    }

4 数据操作

4-1 获取或设置模型的数据

$model->data()

public function data($data, $value = null)
    {
        if (is_string($data)) {
            $this->data[$data] = $value;
        } else {
            // 清空数据
            $this->data = [];
            if (is_object($data)) {
                $data = get_object_vars($data);
            }
            if (true === $value) {
                // 数据对象赋值
                foreach ($data as $key => $value) {
                    $this->setAttr($key, $value, $data);
                }
            } else {
                $this->data = $data;
            }
        }
        return $this;
    }

4-2 获取对象原始数据

$model->getData()

public function getData($name = null)
    {
        if (is_null($name)) {
            return $this->data;
        } elseif (array_key_exists($name, $this->data)) {
            return $this->data[$name];
        } else {
            throw new InvalidArgumentException('property not exists:' . $this->class . '->' . $name);
        }
    }

4-3 数据转换

$model->toArray()

模型数据转换为数组格式

public function toArray()
    {
        $item = [];

        //过滤属性
        if (!empty($this->visible)) {
            $data = array_intersect_key($this->data, array_flip($this->visible));
        } elseif (!empty($this->hidden)) {
            $data = array_diff_key($this->data, array_flip($this->hidden));
        } else {
            $data = $this->data;
        }

        foreach ($data as $key => $val) {
            if ($val instanceof Model || $val instanceof Collection) {
                // 关联模型对象
                $item[$key] = $val->toArray();
            } elseif (is_array($val) && reset($val) instanceof Model) {
                // 关联模型数据集
                $arr = [];
                foreach ($val as $k => $value) {
                    $arr[$k] = $value->toArray();
                }
                $item[$key] = $arr;
            } else {
                // 模型属性
                $item[$key] = $this->getAttr($key);
            }
        }
        // 追加属性(必须定义获取器)
        if (!empty($this->append)) {
            foreach ($this->append as $name) {
                $item[$name] = $this->getAttr($name);
            }
        }
        return !empty($item) ? $item : [];
    }

$model->toJson()

模型数据转换为json格式

public function toJson($options = JSON_UNESCAPED_UNICODE)
    {
        return json_encode($this->toArray(), $options);
    }

$model-readTransform()

数据读取时 类型自动转换

protected function readTransform($value, $type)
    {
        if (is_array($type)) {
            list($type, $param) = $type;
        } elseif (strpos($type, ':')) {
            list($type, $param) = explode(':', $type, 2);
        }
        switch ($type) {
            case 'integer':
                $value = (int) $value;
                break;
            case 'float':
                if (empty($param)) {
                    $value = (float) $value;
                } else {
                    $value = (float) number_format($value, $param);
                }
                break;
            case 'boolean':
                $value = (bool) $value;
                break;
            case 'timestamp':
                $format = !empty($param) ? $param : $this->dateFormat;
                $value  = date($format, $value);
                break;
            case 'datetime':
                $format = !empty($param) ? $param : $this->dateFormat;
                $value  = date($format, strtotime($value));
                break;
            case 'json':
                $value = json_decode($value, true);
                break;
            case 'array':
                $value = is_null($value) ? [] : json_decode($value, true);
                break;
            case 'object':
                $value = empty($value) ? new \stdClass() : json_decode($value);
                break;
            case 'serialize':
                $value = unserialize($value);
                break;
        }
        return $value;
    }

$model->getAttr()

数据获取 自动转换获取器

public function getAttr($name)
    {
        try {
            $notFound = false;
            $value    = $this->getData($name);
        } catch (InvalidArgumentException $e) {
            $notFound = true;
            $value    = null;
        }

        // 检测属性获取器
        $method = 'get' . Loader::parseName($name, 1) . 'Attr';
        if (method_exists($this, $method)) {
            $value = $this->$method($value, $this->data);
        } elseif (isset($this->type[$name])) {
            // 类型转换
            $value = $this->readTransform($value, $this->type[$name]);
        } elseif ($notFound) {
            if (method_exists($this, $name) && !method_exists('\think\Model', $name)) {
                // 不存在该字段 获取关联数据
                $value = $this->relation()->getRelation($name);
                // 保存关联对象值
                $this->data[$name] = $value;
            } else {
                throw new InvalidArgumentException('property not exists:' . $this->class . '->' . $name);
            }
        }
        return $value;
    }

$model->writeTransform()

数据写入 类型转换

protected function writeTransform($value, $type)
    {
        if (is_array($type)) {
            list($type, $param) = $type;
        } elseif (strpos($type, ':')) {
            list($type, $param) = explode(':', $type, 2);
        }
        switch ($type) {
            case 'integer':
                $value = (int) $value;
                break;
            case 'float':
                if (empty($param)) {
                    $value = (float) $value;
                } else {
                    $value = (float) number_format($value, $param);
                }
                break;
            case 'boolean':
                $value = (bool) $value;
                break;
            case 'timestamp':
                if (!is_numeric($value)) {
                    $value = strtotime($value);
                }
                break;
            case 'datetime':
                $format = !empty($param) ? $param : $this->dateFormat;
                $value  = date($format, is_numeric($value) ? $value : strtotime($value));
                break;
            case 'object':
                if (is_object($value)) {
                    $value = json_encode($value, JSON_FORCE_OBJECT);
                }
                break;
            case 'array':
                $value = (array) $value;
            case 'json':
                $option = !empty($param) ? (int) $param : JSON_UNESCAPED_UNICODE;
                $value  = json_encode($value, $option);
                break;
            case 'serialize':
                $value = serialize($value);
                break;
        }
        return $value;
    }

$model->setAttr()

数据写入 自动转换 修改器

public function setAttr($name, $value, $data = [])
    {
        if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) {
            // 自动写入的时间戳字段
            $value = $this->autoWriteTimestamp($name);
        } else {
            // 检测修改器
            $method = 'set' . Loader::parseName($name, 1) . 'Attr';
            if (method_exists($this, $method)) {
                $value = $this->$method($value, array_merge($data, $this->data));
            } elseif (isset($this->type[$name])) {
                // 类型转换
                $value = $this->writeTransform($value, $this->type[$name]);
            }
        }

        // 标记字段更改
        if (!isset($this->data[$name]) || ($this->data[$name] != $value && !in_array($name, $this->change))) {
            $this->change[] = $name;
        }
        // 设置数据对象属性
        $this->data[$name] = $value;
        return $this;
    }

$model->autoWrite()

自动写入时间戳

protected function autoWriteTimestamp($name)
    {
        if (isset($this->type[$name])) {
            $type = $this->type[$name];
            if (strpos($type, ':')) {
                list($type, $param) = explode(':', $type, 2);
            }
            switch ($type) {
                case 'datetime':
                case 'date':
                    $format = !empty($param) ? $param : $this->dateFormat;
                    $value  = date($format, $_SERVER['REQUEST_TIME']);
                    break;
                case 'timestamp':
                case 'int':
                    $value = $_SERVER['REQUEST_TIME'];
                    break;
            }
        } elseif (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), ['datetime', 'date', 'timestamp'])) {
            $value = date($this->dateFormat, $_SERVER['REQUEST_TIME']);
        } else {
            $value = $_SERVER['REQUEST_TIME'];
        }
        return $value;
    }

4-4 模型数据与数据表的操作

Model::create()

写入数据

public static function create($data = [])
    {
        $model = new static();
        $model->isUpdate(false)->save($data, []);
        return $model;
    }

Model::update()

更新数据

public static function update($data = [], $where = [])
    {
        $model  = new static();
        $result = $model->isUpdate(true)->save($data, $where);
        return $model;
    }

Model::destroy()

删除数据

public static function destroy($data)
    {
        $model = new static();
        $query = $model->db();
        if (is_array($data) && key($data) !== 0) {
            $query->where($data);
            $data = null;
        } elseif ($data instanceof \Closure) {
            call_user_func_array($data, [ & $query]);
            $data = null;
        } elseif (is_null($data)) {
            return 0;
        }
        $resultSet = $query->select($data);
        $count     = 0;
        if ($resultSet) {
            foreach ($resultSet as $data) {
                $result = $data->delete();
                $count += $result;
            }
        }
        return $count;
    }

$model->save()

更新数据

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->field)) {
            foreach ($this->data as $key => $val) {
                if (!in_array($key, $this->field) && !array_key_exists($key, $this->field)) {
                    unset($this->data[$key]);
                }
            }
        }

        // 数据自动完成
        $this->autoCompleteData($this->auto);

        // 自动写入更新时间
        if ($this->autoWriteTimestamp && $this->updateTime) {
            $this->setAttr($this->updateTime, null);
        }

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

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

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

            // 去除没有更新的字段
            $data = [];
            foreach ($this->data as $key => $val) {
                if (in_array($key, $this->change) || $this->isPk($key)) {
                    $data[$key] = $val;
                }
            }

            if (!empty($this->readonly)) {
                // 只读字段不允许更新
                foreach ($this->readonly as $key => $field) {
                    if (isset($data[$field])) {
                        unset($data[$field]);
                    }
                }
            }

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

            if (!empty($where)) {
                $pk = $this->getPk();
                if (is_string($pk) && isset($data[$pk])) {
                    unset($data[$pk]);
                }
            }

            $result = $this->db()->where($where)->update($data);
            // 清空change
            $this->change = [];
            // 更新回调
            $this->trigger('after_update', $this);
        } else {
            // 自动写入
            $this->autoCompleteData($this->insert);

            // 自动写入创建时间
            if ($this->autoWriteTimestamp && $this->createTime) {
                $this->setAttr($this->createTime, null);
            }

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

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

            // 获取自动增长主键
            if ($result) {
                $insertId = $this->db()->getLastInsID($sequence);
                $pk       = $this->getPk();
                if (is_string($pk) && $insertId) {
                    $this->data[$pk] = $insertId;
                }
            }
            // 标记为更新
            $this->isUpdate = true;
            // 清空change
            $this->change = [];
            // 新增回调
            $this->trigger('after_insert', $this);
        }
        // 写入回调
        $this->trigger('after_write', $this);

        return $result;
    }

$model->saveAll()

更新多条记录

public function saveAll($dataSet, $replace = true)
    {
        if ($this->validate) {
            // 数据批量验证
            $validate = $this->validate;
            foreach ($dataSet as $data) {
                if (!$this->validate($validate)->validateData($data)) {
                    return false;
                }
            }
        }

        $result = [];
        $db     = $this->db();
        $db->startTrans();
        try {
            $pk = $this->getPk();
            if (is_string($pk) && $replace) {
                $auto = true;
            }
            foreach ($dataSet as $key => $data) {
                if (!empty($auto) && isset($data[$pk])) {
                    $result[$key] = self::update($data);
                } else {
                    $result[$key] = self::create($data);
                }
            }
            $db->commit();
            return $result;
        } catch (\Exception $e) {
            $db->rollback();
            throw $e;
        }
    }

$model->delte()

删除当前记录

public function delete()
    {
        if (false === $this->trigger('before_delete', $this)) {
            return false;
        }

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

        $this->trigger('after_delete', $this);
        return $result;
    }

$model->get()

查找单条记录

public static function get($data = null, $with = [], $cache = false)
    {
        $query = static::parseQuery($data, $with, $cache);
        return $query->find($data);
    }

$model->all()

查找多条记录

public static function all($data = null, $with = [], $cache = false)
    {
        $query = static::parseQuery($data, $with, $cache);
        return $query->select($data);
    }

5 数据表关联操作

5-1 关联查询对象创建

$model->relation()

创建关联对象

protected function relation($relation = null)
    {
        if (!is_null($relation)) {
            // 执行关联查询
            return $this->db()->relation($relation);
        }

        // 获取关联对象实例
        if (is_null($this->relation)) {
            $this->relation = new Relation($this);
        }
        return $this->relation;
    }

5-2 表的关联操作

$model->hasOne()

一对一关联

 public function hasOne($model, $foreignKey = '', $localKey = '', $alias = [], $joinType = 'INNER')
    {
        // 记录当前关联信息
        $model      = $this->parseModel($model);
        $localKey   = $localKey ?: $this->getPk();
        $foreignKey = $foreignKey ?: Loader::parseName($this->name) . '_id';
        return $this->relation()->hasOne($model, $foreignKey, $localKey, $alias, $joinType);
    }

$model->hasMany()

一对多

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);
    }

$model->hasManyThrough()

远程一对多

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);
    }

$model->belongsToMany()

多对多关联

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);
    }

$model->belongTo()

相对关联

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);
    }

5-3 数据的关联操作

数据的关联操作与普通模型的数据操作相同
在建立好关联对象后,即可使用普通数据操作来操作关联数据

6 操作拦截

$model->__call()

对于不存在Model的方法则调用$query数据库对象的方法

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);
        }
    }

Model::__callStatic()

对于不存在Model的静态方法则调用连接对象的静态方法。

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);
    }

$model->__set()

属性修改操作

public function __set($name, $value)
    {
        $this->setAttr($name, $value);
    }

$model->__get()

属性获取操作

public function __get($name)
    {
        return $this->getAttr($name);
    }

$model->_unset()

销毁数据对象的值

public function __unset($name)
    {
        unset($this->data[$name]);
    }

$model->__isset()

属性值检测

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;
        }

    }

7 接口操作

7-1 JsonSerializable

$model->jsonSerialize()

public function jsonSerialize()
    {
        return $this->toArray();
    }

7-2 ArrayAccess

$model->offsetSet()

public function offsetSet($name, $value)
    {
        $this->setAttr($name, $value);
    }

$model->offsetExists()

public function offsetExists($name)
    {
        return $this->__isset($name);
    }

$model->offsetUnset()

public function offsetUnset($name)
    {
        $this->__unset($name);
    }

$model->offsetGet()

public function offsetGet($name)
    {
        return $this->getAttr($name);
    }
网上商城UML图全套:用例图、类图、时序图、活动图建模指南 UML是软件工程中用于可视化系统结构的标准建模语言,通过用例图界定系统边界,类图描述静态结构,时序图和活动图刻画动态行为。掌握UML建模不仅有助于课程设计与软考复习,更能在电商系统开发中避免用例与类图脱节、图图不一致等典型问题。本文以网上商城为例,完整梳理了从需求分析、用例识别到类图、时序图、活动图、协作图及数据库表映射的全过程,并提供可直接复用的建模底稿与避坑指南,适合需要快速产出成套UML文档的开发者参考。 阅读详情

相关推荐

从工艺文件到寄生分析:手把手教你用华大九天RCExplorer做版图预检(附ITF文件解析)

本文详细介绍了华大九天RCExplorer工具在模拟IC和版图设计中的应用,从工艺文件解析到寄生参数提取的全流程。通过ITF文件的深度解析和实战案例,帮助工程师掌握金属层、介质层及通孔参数的关键影响,提升设计效率与准确性。文章还提供了与StarRC工作流集成的实用技巧,是国产EDA工具应用的权威指南。

weixin_42522552的博客 408

tp5.1 model 获取器中的 visible hidden getRelation简单实用

$goods_lists = $this->model ->with([ "info" => function ($query) { $query->where(['is_del' => 0]); } ]) ->where($this->model->getCategoryI...

jim的博客 3192

别再手动调参了!用MATLAB+改进PSO算法,5步搞定机械臂轨迹优化(附完整代码)

本文介绍如何利用MATLAB和改进PSO算法快速优化机械臂轨迹规划,仅需5步即可完成传统耗时的手动调参过程。通过混沌初始化、自适应权重等创新方法,改进PSO算法显著提升优化效率,实现全局最优解搜索,适用于工业自动化中的机械臂控制。文章包含完整MATLAB代码实现,帮助工程师轻松应用于实际生产场景。

weixin_29232121的博客 356

[ POP链 ] thinkphp5.1.x~5.2.x

thinkphp 5.1.x~5.2.x反序列化思路学习 起点:/thinkphp/library/think/process/pipes/Windows.php的__destruct() __destruct()里面调用了两个函数,一个关闭连接close()方法,忽略,然后我们跟进removeFiles()函数。 这里使用了$this->files,而且这里的$files是可控的。所以存在一个任意文件删除的漏洞。 POC可以这样构造: namespace think\process\pipes;

Dannie01的博客 617

【MM小贴士】关于SAP系统中关税的处理方式

的运费,这部分来讲,我们关税的计价基础,就应该是货物价值+包邮到中国港口的运费,完后进行报关操作,缴纳关税,后半段从中国港口拉回到企业里面的运输费,就会做到费用里面去,而不是计入到存货成本。1、我们自己的企业和国外厂家A购买一项物资,厂家A的报价会分成几个组成部分货物本身的价值或者货物本身的价值+到国外港口的运费或者货物本身的价值+到中国港口的运费或者货物本身的价值+包邮到你们自己企业的整体运费。所以我的关税就是不确定的。重点是运费是哪一段的运费,如何结算,结算的货币,何时能够确定运费。.........

竹大的博客 9029

NotebookLM平替实测:用Open Notebook+Ollama零成本搭建私有AI知识库

本文提供了一份详细的实战指南,教你如何利用Open Notebook与Ollama,在本地零成本搭建一个功能强大且完全私有的AI知识库。通过Docker容器化部署,实现数据绝对安全、模型自由选择与离线运行,是NotebookLM等云端工具的绝佳平替方案,尤其适合注重数据隐私的教育工作者、研究者及小团队。

weixin_29052717的博客 514

thinkphp5 模型关联操作

        /*          $user = Users::get ( 1 );          //获取第一个用户的所有信息,返回的是一个$user对像          echo $user->nickname.'<br>';//把字段变成属性访问          print_r($user->comm); //这是属性不是方法,返回的是USERS模型的C...

yefeng215315434的专栏 1194

多旋翼飞行器设计与控制·Pixhawk4以及外部设备接线(笔记004)

笔记主要来源:Pixhawk 4 接线快速入门 目录 一、Pixhawk 4 的各个接口 二、接线图概览(重要传感器及外围设备) 三、飞控、GPS的安装和方向 四、电源 五、无线电遥控 六、数传电台(可选) 七、SD Card(可选) 八、电机以及其他外设 一、Pixhawk 4 的各个接口 FMU:Flight Management Unit 飞行管理组件 主 FMU 处理器:STM32F765 32 位 Arm® Cortex®-M7,216MHz,2MB...

猪猪的博客 1万+

tp5.0 中类的操作注意事项

1:类里面用到静态方法的时候,方法里面要用new self(); 或者 new static(); public static function getActivityLists($wxapp_id,$user_id) { $model = new self(); $model = new static(); } 2:在每一次对数据库进行增删改查的时候都要抛出异常 t...

weixin_37933545的博客 246

【学习体会】Lighttools8.4.0:矩形阵列光源+条形光源的光学仿真分析

在solidworks中设计了条形光源的基本结构: 由32*6个矩形led组成矩形光源阵列,如下所示 另存为step文件后,导入lighttools中,这里要设置模型的光学属性为:吸收体(机械) 因为我们设计的光源模型是一个整体,我们不能单个面的设置光源,比如说, 这样做的话并不会是这个面设置为光源,而是会把做一个模型都变成一个光源,如下 这显然不是我们想要的 那么,我们就在led位置上放置一个矩形面光源, 这样我们就放置好了一个面光源, 但是问题是,还有191...

LeonJin的博客 1万+

YOLO26涨点改进 | 全网独家首发 主干改进篇 | TGRS 2025 | RepViT-TD,告别庞大骨干!YOLO26 + RepViT-TD轻量又强大,实现更快更准的小目标检测!

本文提出将RepViT-TD轻量级主干网络应用于YOLO26目标检测框架,以提升小目标检测性能。RepViT-TD通过优化计算资源分配,强化前两层高分辨率特征提取能力,在保持轻量化的同时(仅4.85M参数)显著提升微小目标的检测精度(AI-TODv2数据集AP50达54.6%)。文章详细介绍了三种主干改进方案(RepVit_ldy1/2/3)的代码实现,并提供了完整的YAML配置文件修改指南,使模型能高效部署于边缘设备。实验表明,该方法在计算复杂度(38.19G FLOPs)和检测精度间取得了良好平衡。

Ai缝合怪、助力小伙伴高效发论文 329

YOLOv5全面解析教程④:目标检测模型精确度评估

指标评估(一些重要的定义)IOU(Intersection Over Union) 基于Jaccard索引,用于评估两个边界框之间的重叠程度。它需要一个真实回归框 (a ground truth bounding box)和一个预测回归框(a pr...

OneFlow深度学习框架 4297

基于STM32设计的太阳能智慧路灯_444

本文设计并实现了一种基于 STM32 的太阳能智慧路灯系统。系统以 STM32F103C8T6 单片机为核心,集成温湿度检测、空气质量检测、环境光照检测、行人检测和路灯故障检测等功能,实现对路灯运行环境和工作状态的实时感知。

464

对TP5数据库缓存cache的一些思考

最近在优化代码的时候,突然想起来TP5的数据库操作中有个cache,之前也用过,印象里就是在缓存时间内,请求的速度会大大加快,但是修改数据会导致不能及时更新。当初还比较年轻,没有深入去搞清楚,只是不再使用cache了而已,现在刚好有机会,就来稍微学一学吧。 很可惜,不论是官方文档还是网上搜索出来的结果,基本上都只是告诉我们如何去使用它,完全没有说到它的工作原理之类的,无奈,只能去慢慢读源码了。 首先让我感到疑惑的是,这个cache和我们平常用的缓存Cache有什么区别? 如果单单从功能上.

weixin_43844995的博客 3859

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

ThinkPHP 5.0 alias别名不生效的解决方法

最近遇到一个问题,就是tp5.0.*调用模型时别名失效,翻找资料之后发现是源码的问题: 源码: 添加已下代码解决: if (false !== strpos($table, '__')) { $table = $this->parseSqlTable($table); }

weixin_45465762的博客 1081

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

TP5源码分析

UP

萌萌程序员的博客 354

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

TP5中模型使用join关联查询时,出现找不到表的情况

问题场景: tp的大版本为5.0 模型之间是一对一的join形式关联,不附加筛选条件的情况下查询是正常的,但是一旦附加了时间范围查询就报错了,报:表不存在错误 问题排查: 经过排查发现是因为使用了tp的between time导致的。 源码分析: 经过分析tp5的框架源码,发现具体原因出在:thinkphp/library/think/db/Builder.php的parseDateTime方法中,parseDateTime单纯靠list($table, $key) = explode('.', $key)

Hey_JC的博客 1255

【TP5.1】 关联查询时,注意BETWEEN TIME查询

  $this->model ->with(['Task'=>function($query){ $query->where($where); }]) ->alias(['__TASK__'=>'task']) ...

iDark 的博客空间 9063

TP框架的Container容器类源码分析

TP框架的Container源码分析 版本:5.1.39TLS Container的结构导图 Container结构图 Container中的属性 $instance——用于容器自身实例化 $instances——一个用于存放容器中的对象实例的数组 $name——容器表示别名 $bind——容器绑定标识 $bind的初始值 /** * 容器绑定标识 * @var array */ protected $bind = [ 'a

qq_43287952的博客 1017

TP5源码分析前置知识-注册树模式

文章目录一、白话解释一下二、看看代码吧三、TP5中的容器四、叨叨一下 一、白话解释一下 所谓注册树也就是在一棵树上种上果子(对象),吃的时候直接在树上去摘,是不是很方便了 二、看看代码吧 class Register { public static $obj = []; public static function set($type,$obj) { self::$obj[$type] = $obj; } public static fun

北漂猿 313

TP5 源码分析-App类里面的$this解析

这个类里面有很这样的使用例如$this->hook->import(); $this->config->get(); $this->request->init();等等 你知道这个对象怎么来的吗?不急,亮仔一一道来: app类会继承容器Container(这是关键) 容器有个魔术方法很重要 例如当调用$this->hook时找不到会调用魔术方法 public function __get($name) { return $t.

北漂猿 629

tp5数据库连接源码分析

今天研究了一下tp5的数据库连接的源码部分。仅限于数据库连接,后期我会再着重分析一下数据库查询的源码。 我们在使用tp5操作数据库的时候,基本上都是通过Db类实现的。或者是使用db()函数。其实db()函数也是通过Db类实现的。那么在tp5中连接数据库都涉及到了哪些文件呢? think\Db think\db\connector\Mysql (我们经常用到的就是mysql数据库,所以就以...

范范范国超的博客 428

tp5源码分析之自动加载

1 自动加载自动加载,在php中主要包括命名空间到目录的定位,类名到文件的定位。tp5的自动加载实现在Loader.php中。1 启动自动加载Loader::register()启动自动加载public static function register($autoload = '') { // 注册系统自动加载 spl_autoload_register($...

An丶的博客 1526

代码审计 - TP5 框架审计写法分析及代码追踪

本次课程主要围绕 TP5 框架开发的成品源码审计展开。重点讲解了三种代码写法(支线写法、不安全写法、规矩写法)的分析思路,以及相关的审计基础技术,包括调试开关开启、代码追踪方法和输出角色相关内容。通过示例和实际源码分析,帮助理解不同写法在安全性分析上的差异。在对 TP5 框架的代码审计中,要先确定代码的写法类型,然后根据不同类型的特点和原理进行分析。结合前端和后端代码的交互情况,充分利用调试工具和技术,全面检查可能存在的安全漏洞。对于发现的问题,要及时采取措施修复,确保系统的安全性。

m0_57836225的博客 1206

tp5源码分析之模板引擎

1 模板引擎模板引擎,负责将模板变量填充到模板文件中,默认模板引擎实现在\view\Think.php文件中tp5还支持php文件的模板,其接口与Think模板引擎一致。具体见\view\Php.php文件。$think->__construct()模板引擎构造函数,创建模板引擎对象public function __construct($config = []) { ...

An丶的博客 5699

*【思路】查看php框架tp5、yii2、laravel源码的思路

建议自己先做一遍框架,在看源码就会更方便了 等有时间咯,在写分析各个框架的思路吧 此思路是看第3方类库或某个框架文档特少的方法: 1、根据想要实现的功能名:找类 2、找到后挨着看方法:找到方法 3、调用该方法测试下,一般只看这2点一般就够了 3.1、看该方法得注释需要传什么参数 3.2、看该方法得注释返回什么数据类型。 这2点没问题一般也就对了,具体代码的实现有空咯在看 ...

西瓜的博客 1759
上一篇: tp5源码分析之查询构造
下一篇: tp5源码分析之视图
code301
博客等级 码龄9年 87粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值