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