discuz X論壇技術架構 MVC結構淺析


摘自: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()這個函數,稍后可以簡單的說下這個函數的相關過程。

接下來說下執行的相關流程,先看下一些代碼

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. 以上可能會有理解錯誤的地方,歡迎指出或補充  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM