zoukankan      html  css  js  c++  java
  • discuz X论坛技术架构 MVC结构浅析

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

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

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

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

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

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

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

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

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

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

    接下来说下执行的相关流程,先看下一些代码

    Php代码 复制代码 收藏代码
    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.   
    12. require DISCUZ_ROOT.'./source/function/function_home.php';   
    13. require DISCUZ_ROOT.'./source/function/function_portal.php';   
    14. //包含protal.php对应的核心函数文件   
    15. if(emptyempty($_GET['mod']) || !in_array($_GET['mod'], array('list''view''comment''portalcp''topic''attachment'))) $_GET['mod'] = 'index';   
    16. 检查mod,是否在mod列表里,如果不在或者不对应,则默认为index   
    17. define('CURMODULE'$_GET['mod']);   
    18. runhooks();//这个是用来检查加载插件的   
    19.   
    20. $navtitle = str_replace('{bbname}'$_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);   
    21.   
    22. require_once libfile('portal/'.$_GET['mod'], 'module');   
    23. //这个是用来加截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()这个函数

    Php代码 复制代码 收藏代码
    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这个文件

    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.   
    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');  
    if(!defined('IN_DISCUZ')) {
    	exit('Access Denied');
    }
    //上面是用来检查discuz核心文件是否加载,
    $navtitle = str_replace('{bbname}', $_G['setting']['bbname'], $_G['setting']['seotitle']['portal']);
    if(!$navtitle) {
    	$navtitle = $_G['setting']['navs'][1]['navname'];
    } else {
    	$nobbname = true;
    }
    
    $metakeywords = $_G['setting']['seokeywords']['portal'];
    if(!$metakeywords) {
    	$metakeywords = $_G['setting']['navs'][1]['navname'];
    }
    
    $metadescription = $_G['setting']['seodescription']['portal'];
    if(!$metadescription) {
    	$metadescription = $_G['setting']['navs'][1]['navname'];
    }
    上面是一些文件头信息,
    include_once template('diy:portal/index');
    
    


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

    看下checktplrefresh()这个函数

    Php代码 复制代码 收藏代码
      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.   
      20. 由此以来,先是调用source/module/下的相关文件进行读取数据库或者是读取缓存数据的相关功能把,相关变量赋值然后用template和template类进行对模板解析,变量替换,然后显示到前台,大致的过程就是这样的。   
      21.   
      22. 当然中间还有一些缓存的相关判断,这部分还在研究之中,稍候会贴出来。   
      23.   
      24. 以上可能会有理解错误的地方,欢迎指出或补充  
  • 相关阅读:
    Postman初探
    web页面和本地数据对比问题
    Katalon Recorder初探
    Flask入门
    自我实现预言
    gulp 安装 依赖
    maven环境
    加解密 生成 X.509格式,DER编码,后缀名.cer。加密公钥证书
    我的魔法 公式找回中
    gulp 自动ftp至服务器时,处理开发 测试服务器地址问题
  • 原文地址:https://www.cnblogs.com/wellsoho/p/3723028.html
Copyright © 2011-2022 走看看