TP5_模型初始化_踩坑记录

简介: 前言:先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法,把对数据库的操作,写到一个模型里,通过去换模型属性中的table来达到代码不变操作的数据表变化的效果。

前言:

先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法,把对数据库的操作,写到一个模型里,通过去换模型属性中的table来达到代码不变操作的数据表变化的效果。
我们都知道,模型要想关联数据表的话,有两中方式,第一种就是将模型名和数据表一致。这样模型就会默认关联到名字对应的数据表。第二种就是定义模型的 protected $table 来指定表明。我当时就想,有没有什么方法,能初始化模型对象的时候将table属性赋值呢,这个值存在数据库里。这样就可以动态的来控制这个模型关联的表名了。

模型初始化

基于以上的需求,文档里的模型初始化引起了我的注意


tp5文档

我感觉这是我要找的东西。紧接着我着手开始测试

首次测试

我根据手册的写法,在调用父类初始化后面,写上对table的初始化,那么现在我们来打印出来实例化的order模型


打印实例化对象

从图中大家可以发现,table属性的确已经修改了。然后我就没有再做更多的测试了,因为我试过手动将table数据改为别的表名,就可以修改模型所关联的数据表。我想这个table属性已经有了肯定就没问题了。

直到我在这个模型里写了很多方法后,我想去回来换个表名来试试写入数据。爆炸的事情出现了。

      //我使用包含table属性的对象去查数据库。查询出来的结果,居然任然是原来那个模型名对应的表
     $order = new \app\API\model\Order();
     return $order->select();

这就很爆炸了,我已经写好的这么多代码难道都不能用了?

冷静下来之后,我决定先试试,手动在模型中该表table属性来试试。


直接修改模型的table属性

那么我们再来访问下呢?


image.png

报错,报表不存在,这是正确的,因为我没有建立order_1这个表。不过这也说明了,order模型的确已经和order_1表关联起来了。这样就让我摸不着头脑了。以前学习面向对象那些理论又浮现在我们脑海里。我梳理了下思路

  1. order模型中定义table属性,其实是对父类Model中的table的重写。并且table属性是一个protected的。那么就是说,只有在模型内部或则子类中可以使用和修改
  2. 在实例化模型的地方是控制器,也就是类的外部,理论上外部是对象只能读取和操作类中public的属性的
  3. 可是initialize又是在实例化模型自动触发的方法,触发的地方又是在模型的内部。
  4. 但是我又是使用$this 又是指代我控制器中的被实例化出来的模型对象。那是不是还是不能访问被保护的属性呢?
    好了瞎分析完了之后,我决定还是去网上搜索下,看看有没有人和我一样的应用场景。后来我发现,使用模型初始化的人,似乎很少。少数几篇博客讲解了下。其中有个应用场景和我类似。他在代码中是这样写的
    protected function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->table('order_1');//假装这里名字是从数据库里取得
    }

我通过IDE的智能感知,进入套table方法中,看了下注释


image.png

看样子是我需要的方法,可这个方法不是模型基类里的啊,是在query类当中的。我有些摸不清楚头脑,但不管怎样,还是要试一试

为了让代码不报错,我去增加了一个order_1表。这一试,嘿嘿,搞定了!


image.png

打印出了我在新表中的一条数据。哈哈,看来这个思路是可行的

就在我认为这个思路是可行的时候,我在执行我写好的一些模型方法时,我发现了一个大坑!!

我就不详细说我是怎么发现的了。直接看代码
模型里我还是这么写的

    protected function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->table('order_1');//假装这里名字是从数据库里取得
    }
        //控制器里实例化模型后,调用count方法
        $order = new \app\API\model\Order();
        var_dump($order->count());
        var_dump($order->count());die;

结果让人非常的震惊!


结果

同一个对象,调用同一个方法,结果居然不一样!我反复试过都是这样。我决定将他们的sql打印出来看看有什么问题


image.png

结果同样是让人哭笑不得


image.png

结果模型初始化是一次性的?(黑人问号.jpg)

我当时就觉得是tp5的bug,我要向作者反应!

后来我冷静下来,还是先把项目问题解决了来再说哦。饭碗要紧。

最终经过我的摸(luan)索(gao) ,我找到解决方案。下面就把代码贴出来,但是我确实不知道怎么解释这个问题。也希望大神能够指出,感激不尽

   protected function initialize()
    {
        parent::initialize(); // TODO: Change the autogenerated stub
        $this->name('order_1');//将table方法换位name方法
    }

name方法是也是指定表名,只是不带表前缀。经测试,传入不含表前缀的表名可行,我这里的数据表设计的时候没有表前缀,所以传的都一样。

那么改过之后,再来打印下之前的sql


image.png

经测试可以正常切换两个表~

本次博客只在记录,内容中有很多自己瞎猜的,站不住脚,让大神见笑。非常希望能有大神指点

相关文章
|
3月前
|
运维 负载均衡 网络协议
函数计算FC报错问题之测试报错如何解决
函数计算(Function Compute,FC)是一个事件驱动的全托管计算服务,允许用户编写并上传代码,而无需管理服务器运行和维护;在使用过程中,可能会遇到各种报错,本合集聚焦于函数计算FC常见的报错问题,提供一系列的故障排查指导和解决建议,帮助用户优化云端函数执行
69 2
|
6月前
|
前端开发 测试技术
【前端验证】记录将发包量作为传参以加速debug的环境优化记录
【前端验证】记录将发包量作为传参以加速debug的环境优化记录
|
1月前
|
缓存 NoSQL Serverless
函数计算常见问题之创建应用报错如何解决
函数计算(Function Compute, FC)是阿里云提供的无服务器计算服务,它允许用户在无需管理服务器的情况下运行代码,但在配置和执行过程中可能遇到报错,本合集致力于梳理FC服务中的常见报错和配置问题,并提供解决方案,帮助用户优化函数执行环境。
104 1
|
1月前
|
JavaScript 前端开发
v-if 和 v-show 的差异及最优使用场景
v-if和v-show都是Vue.js中的条件渲染指令,它们都可以根据表达式的值来决定是否渲染一个元素。但是它们的工作方式不同,因此在使用上也有一些区别。
|
3月前
|
存储 安全 C++
【C++14保姆级教程】lambda 初始化捕获 new/delete 消除
【C++14保姆级教程】lambda 初始化捕获 new/delete 消除
|
8月前
|
数据采集 缓存 数据挖掘
GATK4标准分析流程 丨如何选择合适的线程和内存大小?数据预处理方法与注意事项
GATK4标准分析流程 丨如何选择合适的线程和内存大小?数据预处理方法与注意事项
|
PHP
tp自动验证流程和返回空数组的问题
tp自动验证流程和返回空数组的问题
89 0
|
分布式计算 大数据 数据处理
Spark 原理_总体介绍_逻辑执行图 | 学习笔记
快速学习 Spark 原理_总体介绍_逻辑执行图
98 0
Spark 原理_总体介绍_逻辑执行图 | 学习笔记
TP5怎么使用模型
TP5怎么使用模型
103 0
【TP5】不重复添加数据(案例:专题下的视频管理)
【TP5】不重复添加数据(案例:专题下的视频管理)
157 0
【TP5】不重复添加数据(案例:专题下的视频管理)