Discuz!官方免费开源建站系统

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索

C::t 方法有癌症,有图示有例证有剖析但无解决方法

[复制链接]
要命的酒鬼 发表于 2012-8-3 14:22:14 | 显示全部楼层 |阅读模式
本帖最后由 要命的酒鬼 于 2012-8-3 16:30 编辑

C::t的优点自不必多说,只说缺陷之处。
先上图看一下t($name)函数的流程图



从上图可以看到以下流程顺序
1、首先判断缓存中是否存在键为(类名=)$classname的$_tables变量
2、其次判断类$classname是否已经定义
3、再次才从插件或系统中装载并实例化$classname
=================================
那么这个流程有什么问题呢,我通过几个示例来剖析
=================================
1、两个(或两个以上)不同插件通过自定义方法调取同一系统表类中数据的情况
问题:为啥不用系统表类已定义好的方法呢?
释疑:因为系统定义的方法无法满足插件的自身需求。
准备:
a.设计两个插件drk_testadrk_testb(注意颜色区别),其中的系统表common_member_profile可任意选择
b.分别添加页面嵌入模块类型drk_hooka.class.php、drk_hookb.class.php
<?php
if(!defined('IN_DISCUZ')){
    exit('Aecsse Denied');
}

class plugin_drk_testa {
        function global_footer() {
        C::t('#drk_testa#common_member_profile')->drk_testa_method();
    }
}
?>


<?php
if(!defined('IN_DISCUZ')){
    exit('Aecsse Denied');
}

class plugin_drk_testb {
        function global_footer() {
        C::t('#drk_testb#common_member_profile')->drk_testb_method();
    }
}
?>

c.分别编写两个同名(系统)表类table_common_member_profile.php置于两个插件的table文件夹中
<?php
if(!defined('IN_DISCUZ')) {
        exit('Access Denied');
}

class table_common_member_profile extends discuz_table{
        public function __construct() {
                $this->_table = 'common_member_profile';
                $this->_pk    = 'uid';
                parent::__construct();
        }

    public function drk_testa_method(){
        return ;
    }
}
?>
<?php
if(!defined('IN_DISCUZ')) {
        exit('Access Denied');
}

class table_common_member_profile extends discuz_table{
        public function __construct() {
                $this->_table = 'common_member_profile';
                $this->_pk    = 'uid';
                parent::__construct();
        }

    public function drk_testb_method(){
        return ;
    }
}
?>

d.以下行为都会抛出Class "table_common_member_profile" does not have a method named "drk_testb_method"异常错误
①先启用运行drk_testa插件,后启用运行drk_testb插件;
②关闭drk_testa插件,依然提示上面的错误
③启用顺序颠倒,错误依旧提示
===================================
2、某个插件使用自定义方法调取某一系统表数据在某个页面发生的情况
准备:
a.设计一个插件drk_test
b.添加页面嵌入模块类型drk_hook.class.php
<?php
if(!defined('IN_DISCUZ')){
    exit('Aecsse Denied');
}

class plugin_drk_test {
        function global_footer() {
        C::t('#drk_test#common_member_profile')->drk_test_method();
    }
}
?>

c.编写同名(系统)表类table_common_member_profile.php置于插件的table文件夹中
<?php
if(!defined('IN_DISCUZ')) {
        exit('Access Denied');
}

class table_common_member_profile extends discuz_table{
        public function __construct() {
                $this->_table = 'common_member_profile';
                $this->_pk    = 'uid';
                parent::__construct();
        }

    public function drk_test_method(){
        return ;
    }
}
?>

d.当插件启用后,凡在系统脚本中有调用该系统表类方法的页面(例如个人资料页 home.php?mod=space&uid=1&do=profile)就会抛出Class "table_common_member_profile" does not have a method named "drk_test_method".
====================================================
剖析:以上两个示例足矣说明了C::t的问题,那么为什么会发生错误呢?原因其实很简单,通过流程图可以看出,无论是插件还是论坛系统,当调用一个系统表类(第一个插件自定义的)方法时,首先在第57行判断该类的实例化缓存是否存在,如果不存在则继续在第58行判断该类是否已定义,如果未定义则加载该类并实例化。注意,此时,这个类已经实例化并缓存了。接下来运行第二个插件并调用同名系统表类(第二个插件自定义)方法,又转到了第57行,因为该类实例化缓存已存在,因此不会去加载和实例化第二个插件的自定义表类,也就是第二个插件依然沿用了上一个已实例化的同名表类,很显然上一个实例化的表类中并没有第二个插件自定义的表类方法,抛出异常也就是必然的了。
====================================================
遗憾:通过示例和剖析可以看出,当对同一个系统表类调用插件自定义方法时,只有最早启用的插件有效,后续的插件都会出错,任你绞尽脑汁也无法修正错误。我现在真的不知该拿C::t怎么办,涉及无满足需求方法的系统表类的插件该怎么设计,要不要抛弃DX2.5,回到DX2?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
520sh 发表于 2012-8-3 14:24:51 | 显示全部楼层
本帖最后由 520sh 于 2012-8-3 14:32 编辑

顶起来,再看

   C::t('#drk_testa#common_member_profile')->drk_testa_method();

   C::t('#drk_testb#common_member_profile')->drk_testb_method();

这里传进去后classname会一样??/
回复

使用道具 举报

 楼主| 要命的酒鬼 发表于 2012-8-3 14:29:04 | 显示全部楼层
擦,那图怎么跑下面去了,怎么就编排不好呢{:soso_e135:}
回复

使用道具 举报

腐朽的木头 发表于 2012-8-3 15:02:06 | 显示全部楼层
看来还是用2.0吧
回复

使用道具 举报

 楼主| 要命的酒鬼 发表于 2012-8-3 16:41:40 | 显示全部楼层
mvntbxxi 发表于 2012-8-3 16:39
一句话的事,楼主在哪里~~!!

什么在哪里?莫非你有解决方案?
回复

使用道具 举报

m.king 发表于 2012-8-3 17:42:46 | 显示全部楼层
文章内容写得很多,问题我们再看看。
回复

使用道具 举报

m.king 发表于 2012-8-3 17:45:23 | 显示全部楼层
问题研发已阅。感谢您的反馈!
回复

使用道具 举报

亘古つ守侯珊 发表于 2012-8-4 09:23:34 | 显示全部楼层
这是所谓的核磁共振吗
回复

使用道具 举报

1314学习网 发表于 2012-8-4 10:45:46 | 显示全部楼层
貌似和我第一次用X2.5就遇到类似问题的了,就是操作系统表,死的惨,然后懒得用了
回复

使用道具 举报

 楼主| 要命的酒鬼 发表于 2012-8-12 17:44:37 | 显示全部楼层
功夫不负有心人,已经找到解决方案
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|Discuz! 官方站 ( 皖ICP备16010102号 )star

GMT+8, 2024-11-16 13:27 , Processed in 0.033593 second(s), 3 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表