Discuz!X 系列的内核是使用面向对象模式开发的,所以每一次页面访问其实都有一个内核实例化的过程,下文将简单介绍一下内核的实现,以及提供的相关功能。
一、实例化操做
一般只有经过 Discuz 入口文件对站点进行访问才会正常进行内核实例化,这些入口文件位于 Dz 根目录下,如:forum.php、home.php、plugin.php 等等。想绕过这些入口文件而直接访问 Dz 目录中的文件则会被拒绝,一般咱们会看到 “Access Denied” 的提示。缘由是,除了入口文件和一些专用 API 接口文件外全部源码文件的开头都有以下代码:php
而 IN_DISCUZ 这个常量只有实例化的时候才会被定义,任何绕过入口文件而直接执行代码由于 IN_DISCUZ 未被赋值而显示 “Access Denied” 提示。
要实例化内核对象只须要三条语句,代码以下:数据库
初始化完成之后,Dz 内核所集成的功能就可使用了,好比包含整个内核信息的全局变量 $_G,各类缓存接口,模块实例化接口,数据库操做接口等等。
二、实例化过程
经过阅读源码,咱们能够知道:class_core.php 中首先建立实例数组
大写 C 其实只是内核对象的一个简写形式浏览器
所以 C 就表明内核,同时内核还封装了一个很重要的成员函数,即:t(),在 Dz 源码中随处可见相似 C::t('forum_post')->fetch 之类的调用,这实际上是数据库操做函数,相关的数据库操做,后文再详述。
静态成员函数 creatapp 用于建立内核实例,而内核的核心实际上是定义在 discuz_application 类中,参考代码以下:缓存
实例化首先会调用构造函数,构造函数会对基本的运行环境、系统配置文件、输入输出作基本的初始化,参考代码以下:安全
_init_env() 函数主要用于检测服务器软件环境,并作相应设置;加载 function_core.php,Dz 内置的经常使用函数都在此文件中;判断来访者是不是机器人,经过 checkrobot() 实现;初始化全局变量 $_G;
_init_config() 函数主要用于读取 Dz 配置文件,Dz 的配置文件位于根目录下的 config 文件夹中,config_global.php 用于 Dz 系统,config_ucenter.php 用于 UCenter 系统;Dz 的配置文件包含了比较多的内容,主要有这么几个部分:数据库访问参数、内存缓存接口参数、页面输出参数、Cookie参数、安全相关参数等等;经过配置文件的合理配置能够实现 Dz 的分布式部署以及对 MySQL 读写分离功能的支持。
_init_input() 函数主要用于对输入内核的数据进行相关处理,好比对 $_GET、$_POST、$_COOKIE 中的数据进行相关处理,将 $_GET 与 $_POST 合并,所以在 Dz 源码中,能够统一使用 $_GET 来处理用户的输入;
_init_output() 则是用于页面输出,即展现给浏览器的部分,根据配置文件的设定,能够实现页面编码,好比 UTF-8 或者 GBK,以及页面是否使用 Gzip 压缩后传输;
构造函数执行完毕后,还须要继续业务系统的初始化,这些工做则是经过 $discuz->init() 来完成, 其中的 init 成员函数实际上是 discuz_application 中提供的,代码以下:服务器
咱们能够看到,初始化内核一共调用了 7 个子模块,分别用于:数据库、系统设置、用户数据、SESSION数据、移动端适配、计划任务、其余附加功能。
_init_db() 用于初始化数据库,Dz 系统会自动检测适合的数据库驱动,也就是接口函数,最终的初始化经过 DB::inti() 完成;
_init_setting() 用于加载系统设置、默认风格参数、自动化任务等等数据;
_init_user() 与 _init_session() 一块儿完成了用户登陆相关的一些初始化工做,好比若是用户以前已经登陆,那么在 session 过时前能够直接访问网站而无需再次登陆;
_init_mobile() 用于识别用户使用的浏览器是不是移动端,若是是则还要进一步分析是新型触摸屏移动设备仍是老式移动设备,并经过设置常量 IN_MOBILE 来标示用户的浏览器属性;
_init_cron() 用于自动任务的初始化,Dz 的自动化任务能够在后台控制面板中看到,好比天天定时清理论坛数据(用户数、帖子访问量等等),须要指出的是 Dz 的自动化任务执行不一样于操做系统提供的自动化任务,好比 Linux 系统的 crontab,区别在于:操做系统的自动化任务严格按照时间设定执行,而 Dz 的自动化任务须要用户访问来触发,也就是说,只有在每次内核实例化而且执行 _init_cron() 函数的时候才会执行,这时 Dz 内置的相关模块会逐个检测设定好的自动化任务,若是知足执行条件,就会自动调用;
_init_misc() 用于一些杂项的设置,包括一些安全设置,好比进行 xss 攻击检测、表单 FORMHASH 常量设置用于防止非法访问、用户状态检测(好比用户id,ip地址是否被封等等)。
到此,整个实例化过程完成,每一个部分的具体细节,有兴趣的同窗就须要仔细去研究源码才能获得答案。
三、内核数据库操做接口
前面讲过 Dz 内核封装了对数据库的操做,经过内核接口,咱们能够很是方便的操做对应的数据表,同时由于内核的面向对象特性,使得咱们能够很容易的扩展接口的功能。在 Dz source/class/table 目录下有不少以 table_ 前缀开头的 php 源码文件,这些文件就是 C::t() 函数加载的对象,例如:C::t('forum_post') 会自动加载 source/class/table/talbe_forum_post.php 文件中的同名类,而这些类均继承自相同的父类 discuz_table;
对数据表经常使用的操做好比 插入、更新、读取等等 都在 discuz_table 类中进行了封装,这里简单介绍下这些函数的使用。
插入操做:session
$data:要插入的数据,必须是 key => value 结构的数组,且 key 应该和对应数据表的相关字段名对应;
$return_insert_id:是否返回插入记录的ID号,若是设置为 true,则插入成功后会返回新记录的主键值,好比用户表就是 uid;
后面两个参数用于 REPLACE INTO 模式或者 静默模式,具体请参考相关数据库知识;
记录跟新操做:app
$val:用于更新数据表的主键值,若是是用户表, $val = 2 表示更新 uid = 2 的用户数据;
$data:要更新的数据字段的值,必须是 key => value 结构的数组,且 key 应该和对应数据表的相关字段名对应;
后面两个参数我也不多用,有兴趣的同窗能够自行研究:)
取数据操做:xss
$id:要取的数据的主键,好比要获取用户2的数据,那么就是 C::t('common_member')->fetch(2);
$force_from_db:用于设置是否强制从数据库中获取数据,默认容许直接从缓存取数据;
其余还有不少内置接口,同窗们能够自行研究源码,若是内置接口没法知足要求,则彻底能够自行对以上接口进行从新封装。
插件数据表的操做方法:插件根目录下建立 table 目录,对应的表名必须是 table_ + 表名的结构,须要注意的是在数据库中手动建立插件数据表时,须要与系统数据表保持相同的前缀,Dz 默认安装时的表前缀都是 pre_ ,所以若是是默认安装,则须要先在数据库中建立表名为 pre_yourtable 的数据表,而后在插件 table 目录下建立对应的数据库操做类,文件名为 table_yourtable.php,最后在插件代码中就能够经过 C::t("#插件ID#yourtable") 加在插件数据表操做类,并同时继承了父类提供的 insert、update、fetch 等操做。
本节完