首页
站长论坛BBS
救助
投稿
discuz视频教程
discuz技术支持
版块
登录
快速注册

discuz X论坛技术架构 MVC结构浅析

建站高手 2015-6-30 [Discuz开发] 来自PC 复制链接
44664
discuz使用视频教程
31idc

马上注册,一起探讨正确快速的建站方法

您需要 登录 才可以下载或查看,没有帐号?快速注册

x
PS:本人刚接触discuz论坛,php水平有限,当中的理解,如有不正确之处,欢迎指出
------------------------------------

第一个文件相当于控制器(C),比如forum.php(根目录下,相当于大模块,应该再加上小模块控制 module),功能是将相应的请求发送到相应的逻辑处理模块

第二个文件就是业务逻辑处理 如forum_post.php(source\module\forum\forum_post.php,Module相当于小模块、功能点) ,功能是帖子的发布处理        

  在第二个文件当中再调用相应的函数库,处理模块业务 如function_forum.php(source\function\function_forum.php)        

  函数库则调用数据库持久层的表对象(M)  在class/table 下的数据表对象与数据库发生交互,比如source\class\table\table_forum_post.php

第三个文件就是模板文件了(V),将获取到得数据填充到页面各模块分工明细,维护简单

如果需要添加新的模块,可以仿造这种模式,而不会太复杂大致是这个样子的

------------------------------------
依我的理解,discuz的MVC结构是这样的:

Model即逻辑处理,应该是source/function,这里面的一些函数是对数据库(表对象class/table),缓存,内存,配置等一些的相关操作。
Control即控制器,应该是source/module对应相关的模块,比如门户的相关操作,就在portal文件夹下,论坛的相关操作是在forum文件夹下。
View模板即最终呈现给用户看的则是template()这个函数,稍后可以简单的说下这个函数的相关过程。

接下来说下执行的相关流程,先看下一些代码
  1. define('APPTYPEID', 4);
  2. define('CURSCRIPT', 'portal');

  3. require './source/class/class_core.php';//这个文件是核心文件,初始化工作是在这里进行的。
  4. $discuz = & discuz_core::instance//实例化对象,这里是一个单件模式
  5. $cachelist = array('userapp', 'portalcategory');
  6. $discuz->cachelist = $cachelist;//声明缓存列表
  7. $discuz->init();
  8. //进行初始化,环境检查,读取配置,设置内存等


  9. require DISCUZ_ROOT.'./source/function/function_home.php';
  10. require DISCUZ_ROOT.'./source/function/function_portal.php';
  11. //包含protal.php对应的核心函数文件
  12. if(empty($_GET['mod']) || !in_array($_GET['mod'], array('list', 'view', 'comment', 'portalcp', 'topic', 'attachment'))) $_GET['mod'] = 'index';
  13. 检查mod,是否在mod列表里,如果不在或者不对应,则默认为index
  14. define('CURMODULE', $_GET['mod']);
  15. runhooks();//这个是用来检查加载插件的

  16. $navtitle = str_replace('{bbname}', $_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);

  17. require_once libfile('portal/'.$_GET['mod'], 'module');
  18. //这个是用来加截source/module下的对应文件的。
复制代码


define('APPTYPEID', 4);
define('CURSCRIPT', 'portal');

require './source/class/class_core.php';//这个文件是核心文件,初始化工作是在这里进行的。
$discuz = & discuz_core::instance//实例化对象,这里是一个单件模式
$cachelist = array('userapp', 'portalcategory');
$discuz->cachelist = $cachelist;//声明缓存列表
$discuz->init();
//进行初始化,环境检查,读取配置,设置内存等


require DISCUZ_ROOT.'./source/function/function_home.php';
require DISCUZ_ROOT.'./source/function/function_portal.php';
//包含protal.php对应的核心函数文件
if(empty($_GET['mod']) || !in_array($_GET['mod'], array('list', 'view', 'comment', 'portalcp', 'topic', 'attachment'))) $_GET['mod'] = 'index';
检查mod,是否在mod列表里,如果不在或者不对应,则默认为index
define('CURMODULE', $_GET['mod']);
runhooks();//这个是用来检查加载插件的

$navtitle = str_replace('{bbname}', $_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);

require_once libfile('portal/'.$_GET['mod'], 'module');
//这个是用来加截source/module下的对应文件的。

接下来我们可以看下libfile()这个函数
  1. //该文件在source/function/function.core.php
  2. //按上面的传入两个参数libfile("portal/index","module")
  3. function libfile($libname, $folder = '') {
  4.         $libpath = DISCUZ_ROOT.'/source/'.$folder;
  5. //$libpath = "disucz/source/module"
  6.         if(strstr($libname, '/')) {
  7.                 list($pre, $name) = explode('/', $libname);
  8.                 return realpath("{$libpath}/{$pre}/{$pre}_{$name}.php");
  9.         } else {
  10.                 return realpath("{$libpath}/{$libname}.php");
  11.         }
  12. //$libname=protal/protal_index.php
  13. //那么返回的文件就应该是disucz/source/module/protal/protal_index.php
  14. }
复制代码


//该文件在source/function/function.core.php
//按上面的传入两个参数libfile("portal/index","module")
function libfile($libname, $folder = '') {
        $libpath = DISCUZ_ROOT.'/source/'.$folder;
//$libpath = "disucz/source/module"
        if(strstr($libname, '/')) {
                list($pre, $name) = explode('/', $libname);
                return realpath("{$libpath}/{$pre}/{$pre}_{$name}.php");
        } else {
                return realpath("{$libpath}/{$libname}.php");
        }
//$libname=protal/protal_index.php
//那么返回的文件就应该是disucz/source/module/protal/protal_index.php
}

那么我们就来看下protal_index.php这个文件
  1. if(!defined('IN_DISCUZ')) {
  2.         exit('Access Denied');
  3. }
  4. //上面是用来检查discuz核心文件是否加载,
  5. $navtitle = str_replace('{bbname}', $_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);
  6. if(!$navtitle) {
  7.         $navtitle = $_G['setting']['navs'][1]['navname'];
  8. } else {
  9.         $nobbname = true;
  10. }

  11. $metakeywords = $_G['setting']['seokeywords']['portal'];
  12. if(!$metakeywords) {
  13.         $metakeywords = $_G['setting']['navs'][1]['navname'];
  14. }

  15. $metadescription = $_G['setting']['seodescription']['portal'];
  16. if(!$metadescription) {
  17.         $metadescription = $_G['setting']['navs'][1]['navname'];
  18. }
  19. 上面是一些文件头信息,
  20. include_once template('diy:portal/index');
复制代码

这个template函数,代码比较长,我就不贴了,大致说下功能。
template主要的功能是用来生成缓存文件的名字,只是用来生成这个名字,实际并未生成,真正生成的是template函数最后的那个checktplrefresh(),看名字,应该猜得出,是检查模板是否更新

看下checktplrefresh()这个函数
  1. function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) {
  2.         static $tplrefresh, $timestamp;
  3.         if($tplrefresh === null) {
  4.                 $tplrefresh = getglobal('config/output/tplrefresh');
  5.                 $timestamp = getglobal('timestamp');
  6.         }
  7. //上面的那段我还不知道是干啥来着,
  8.         if(empty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
  9.                 if(empty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) {
  10.                         require_once DISCUZ_ROOT.'/source/class/class_template.php';
  11.                         $template = new template();
  12.                         $template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
  13.                         return TRUE;
  14.                 }
  15.         }
  16.         return FALSE;
  17. }
复制代码

下面的这个判断主要是看是否在缓存时间内,如果在缓存时间内,则返回false,直接包含之前生成的缓存文件,如果不在缓存时间之后,则进行重新解析。完了之后,就会执行解析好的php缓存文件。显示到前台,大家可以看下parse_template()这个函数用了很正则去解析模板。这个就不多介绍了,大家可以去看下。

由此以来,先是调用source/module/下的相关文件进行读取数据库或者是读取缓存数据的相关功能把,相关变量赋值然后用template和template类进行对模板解析,变量替换,然后显示到前台,大致的过程就是这样的。

当然中间还有一些缓存的相关判断,这部分还在研究之中,稍候会贴出来。

以上可能会有理解错误的地方,欢迎指出或补充



上一篇:Discuz! X系列,缓存扩展机制说明
下一篇:如何copy别人的diy首页模板呢
Neymar 发表于 2015-6-30 14:46:18 来自PC
强烈支持,站帮网有你更精彩
yizong 发表于 2015-6-30 23:10:02 来自PC
宜纵电子  http://www.yz021.cn
MarksGui 发表于 2015-7-1 14:33:07 来自PC
  新手路过,分析的不错!    强烈支持,站帮网有你更精彩
awy123 发表于 2015-7-3 10:18:33 来自PC

支持支持.....................  www.hbcsdzqc.com
www.hbcsdzqc.com随车吊_起重机
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

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