摘自:http://yeyuan.iteye.com/blog/930727

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(emptyempty($_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下的对应文件的。
  1. define('APPTYPEID', 4);
  2. define('CURSCRIPT', 'portal');
  3.  
  4. require './source/class/class_core.php';//这个文件是核心文件,初始化工作是在这里进行的。
  5. $discuz = & discuz_core::instance//实例化对象,这里是一个单件模式
  6. $cachelist = array('userapp', 'portalcategory');
  7. $discuz->cachelist = $cachelist;//声明缓存列表
  8. $discuz->init();
  9. //进行初始化,环境检查,读取配置,设置内存等
  10.  
  11. require DISCUZ_ROOT.'./source/function/function_home.php';
  12. require DISCUZ_ROOT.'./source/function/function_portal.php';
  13. //包含protal.php对应的核心函数文件
  14. if(empty($_GET['mod']) || !in_array($_GET['mod'], array('list', 'view', 'comment', 'portalcp', 'topic', 'attachment'))) $_GET['mod'] = 'index';
  15. 检查mod,是否在mod列表里,如果不在或者不对应,则默认为index
  16. define('CURMODULE', $_GET['mod']);
  17. runhooks();//这个是用来检查加载插件的
  18.  
  19. $navtitle = str_replace('{bbname}', $_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);
  20.  
  21. require_once libfile('portal/'.$_GET['mod'], 'module');
  22. //这个是用来加截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. }
  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. }

那么我们就来看下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');
  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.  
  12. $metakeywords = $_G['setting']['seokeywords']['portal'];
  13. if(!$metakeywords) {
  14. $metakeywords = $_G['setting']['navs'][1]['navname'];
  15. }
  16.  
  17. $metadescription = $_G['setting']['seodescription']['portal'];
  18. if(!$metadescription) {
  19. $metadescription = $_G['setting']['navs'][1]['navname'];
  20. }
  21. 上面是一些文件头信息,
  22. 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(emptyempty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
    9. if(emptyempty($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. }
    18. 下面的这个判断主要是看是否在缓存时间内,如果在缓存时间内,则返回false,直接包含之前生成的缓存文件,如果不在缓存时间之后,则进行重新解析。完了之后,就会执行解析好的php缓存文件。显示到前台,大家可以看下parse_template()这个函数用了很正则去解析模板。这个就不多介绍了,大家可以去看下。
    19. 由此以来,先是调用source/module/下的相关文件进行读取数据库或者是读取缓存数据的相关功能把,相关变量赋值然后用template和template类进行对模板解析,变量替换,然后显示到前台,大致的过程就是这样的。
    20. 当然中间还有一些缓存的相关判断,这部分还在研究之中,稍候会贴出来。
    21. 以上可能会有理解错误的地方,欢迎指出或补充

discuz X论坛技术架构 MVC结构浅析的更多相关文章

  1. sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz!

    sae-v2ex 一个运行在SAE上的类似v2ex的轻型python论坛 - 技术讨论 - 云计算开发者社区 - Powered by Discuz! sae-v2ex 一个运行在SAE上的类似v2e ...

  2. 浅析微信小程序技术架构(原创)

    周末万里虎抽空体验了下微信小程序的DEMO,对小程序的开发有了一个基础的了解与认识,今天就来和大家分享一下我对小程序的看法. 从官方DEMO来看,小程序在技术架构上非常清晰易懂.JS负责业务逻辑的实现 ...

  3. PHP MVC结构系统架构设计

    今天研究了下PHP MVC结构,所以决定自己写个简单的MVC,以待以后有空再丰富.至于什么MVC结构,其实就是三个Model,Contraller,View单词的简称,,Model,主要任务就是把数据 ...

  4. Worktile 技术架构概要

    其实早就该写这篇博客了,一直说忙于工作没有时间,其实时间挤挤总会有的,可能就是因为懒吧!从2013年11月一直拖到现在,今天就简单谈谈 Worktile 的技术架构吧 . Worktile 自上线到现 ...

  5. MVC框架浅析(基于PHP)

    MVC框架浅析(基于PHP) MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑.数 ...

  6. 转载Worktile 技术架构概要

    Worktile 技术架构概要 其实早就该写这篇博客了,一直说忙于工作没有时间,其实时间挤挤总会有的,可能就是因为懒吧!从2013年11月一直拖到现在,今天就简单谈谈 Worktile 的技术架构吧 ...

  7. [转]MVVM架构~mvc,mvp,mvvm大话开篇

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一 ...

  8. 大型网站技术架构(四)--核心架构要素 开启mac上印象笔记的代码块 大型网站技术架构(三)--架构模式 JDK8 stream toMap() java.lang.IllegalStateException: Duplicate key异常解决(key重复)

    大型网站技术架构(四)--核心架构要素   作者:13GitHub:https://github.com/ZHENFENG13版权声明:本文为原创文章,未经允许不得转载.此篇已收录至<大型网站技 ...

  9. 【程序猿笔试面试复习】之中的一个 网络与通信篇(一) 几大网络模型:OSI、TCP/IP、B/S与C/S、MVC结构

    9.1网络模型 9.1.1. OSI七层模型 OSI(Open System Interconnection,开放系统互联)七层网络模型称为开放式网络互联參考模型.其为国际标准组织指定的一个指导信息互 ...

随机推荐

  1. adaptive query processing

    http://www.cs.umd.edu/~amol/talks/VLDB07-AQP-Tutorial.pdf https://www.cis.upenn.edu/~zives/research/ ...

  2. python virtualenv使用

    1.什么是virtualenv virtualenv用来做环境隔离,比如项目A使用了python2,项目B使用了python3 使用virtualenv可以分别生成项目A和项目B的环境包 2.virt ...

  3. 【消息】linux之消息队列

      1.机制 消息队列的运行方式与命名管道非常相似. 欲与其他进程通信的进程只需要将消息发送到消息队列中,目的进程就从消息队列中读取需要的消息. 2.源码 1)发送方 //msg_send.c #in ...

  4. 【转载】一个Sqrt函数引发的血案

    转自:http://www.cnblogs.com/pkuoliver/archive/2010/10/06/sotry-about-sqrt.html 源码下载地址:http://diducoder ...

  5. Pythonic版二分查找

    [本文出自天外归云的博客园] 前提:升序数组,待查元素在数组中. 二分查找:就是一个递归函数c.待查元素a,当前数组中位数b,如果b=a则返回b的索引,b>a则在b左侧的子数组中调用函数c,否则 ...

  6. nginx动态配置及服务发现那些事

    Reference: http://xiaorui.cc/2016/10/16/nginx%E5%8A%A8%E6%80%81%E9%85%8D%E7%BD%AE%E5%8F%8A%E6%9C%8D% ...

  7. Highcharts 多个Y轴动态刷新数据

    效果图: js代码: $(function() { $(document).ready(function() { Highcharts.setOptions({ global: { useUTC: f ...

  8. Sqlserver 2008 error 40出现连接错误的解决方法

    说明(2017-5-25 15:00:16): 核心:把端口号改成1433 Sqlserver 2008 error 40出现连接错误的解决方法

  9. tomcat 远程命令执行漏洞复现

    影响范围 Apache Tomcat 7.0.0 - 7.0.81 不受影响的版本 Apache Tomcat 8.x Apache Tomcat 9.x 漏洞分析 在Tomcat安装目录下的配置文件 ...

  10. sparkonhbase

    import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.client.Result impor ...