TP5_模型初始化_踩坑记录

  1. 云栖社区>
  2. 博客>
  3. 正文

TP5_模型初始化_踩坑记录

勃起狂奔者 2018-04-26 22:42:00 浏览1147
展开阅读全文

前言:

先交代下背景,在一个项目中,有一个数据表有水平分表的需求。当时想找到一种方法,把对数据库的操作,写到一个模型里,通过去换模型属性中的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

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

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

网友评论

登录后评论
0/500
评论
勃起狂奔者
+ 关注