您现在的位置是:首页 > cms教程 > Discuz教程Discuz教程
discuzX论坛技术架构MVC结构分析
书瑶2025-06-25Discuz教程已有人查阅
导读第一个文件相当于控制器(C),比如forum.php(根目录下,相当于大模块,应该再加上小模块控制 module),功能是将相应的请求发送到相应的逻辑处理模块
第一个文件相当于控制器(C),比如forum.php(根目录下,相当于大模块,应该再加上小模块控制module),功能是将相应的请求发送到相应的逻辑处理模块第二个文件就是业务逻辑处理如forum_post.php(source\module\forum\forum_post.php,Module相当于小模块、功能点),功能是帖子的发布处理在第二个文件当中再调用相应的函数库,处理模块业务如
第三个文件就是模板文件了(V),将获取到得数据填充到页面各模块分工明细,维护简单如果需要添加新的模块,可以仿造这种模式,而不会太复杂大致是这个样子的依我的理解,discuz的MVC结构是这样的:
Model即逻辑处理,应该是source/function,这里面的一些函数是对数据库(表对象class/table),缓存,内存,配置等一些的相关操作。
Control即控制器,应该是source/module对应相关的模块,比如门户的相关操作,就在portal文件夹下,论坛的相关操作是在forum文件夹下。
View模板即最终呈现给用户看的则是template()这个函数,稍后可以简单的说下这个函数的相关过程。
接下来说下执行的相关流程,先看下一些代码
template主要的功能是用来生成缓存文件的名字,只是用来生成这个名字,实际并未生成,真正生成的是template函数之后的那个checktplrefresh(),看名字,应该猜得出,是检查模板是否更新
看下checktplrefresh()这个函数
由此以来,先是调用source/module/下的相关文件进行读取数据库或者是读取缓存数据的相关功能把,相关变量赋值然后用template和template类进行对模板解析,变量替换,然后显示到前台,大致的过程就是这样的。
当然中间还有一些缓存的相关判断,这部分还在研究之中,稍候会贴出来。
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()这个函数,稍后可以简单的说下这个函数的相关过程。
接下来说下执行的相关流程,先看下一些代码
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(emptyempty($_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下的对应文件的。
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()这个函数
//该文件在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
}
//该文件在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这个文件
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');
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()这个函数
function checktplrefresh($maintpl, $subtpl, $timecompare, $templateid, $cachefile, $tpldir, $file) {
static $tplrefresh, $timestamp;
if($tplrefresh === null) {
$tplrefresh = getglobal('config/output/tplrefresh');
$timestamp = getglobal('timestamp');
}
//上面的那段我还不知道是干啥来着,
if(emptyempty($timecompare) || $tplrefresh == 1 || ($tplrefresh > 1 && !($timestamp % $tplrefresh))) {
if(emptyempty($timecompare) || @filemtime(DISCUZ_ROOT.$subtpl) > $timecompare) {
require_once DISCUZ_ROOT.'/source/class/class_template.php';
$template = new template();
$template->parse_template($maintpl, $templateid, $tpldir, $file, $cachefile);
return TRUE;
}
}
return FALSE;
}
下面的这个判断主要是看是否在缓存时间内,如果在缓存时间内,则返回false,直接包含之前生成的缓存文件,如果不在缓存时间之后,则进行重新解析。完了之后,就会执行解析好的php缓存文件。显示到前台,大家可以看下parse_template()这个函数用了很正则去解析模板。这个就不多介绍了,大家可以去看下。由此以来,先是调用source/module/下的相关文件进行读取数据库或者是读取缓存数据的相关功能把,相关变量赋值然后用template和template类进行对模板解析,变量替换,然后显示到前台,大致的过程就是这样的。
当然中间还有一些缓存的相关判断,这部分还在研究之中,稍候会贴出来。
本文标签:
很赞哦! ()
相关教程
图文教程
discuz的sphinx全文检索搜索引擎方案
sphinx最主要的就是这个配置文件,当然在增量索引部分可以写一个脚本放到crontab里面来定时跑下面介绍下在discuz中sphinx的php调用部分,sphinx的接口采用PHP的扩展
Discuz论坛注册过程和账号设置基本用法介绍
在discuz论坛上注册和设置账号的步骤如下:1.访问论坛主页,点击注册按钮。2.填写注册表单,包括用户名、密码和邮箱地址。3.完成注册后,登录账号。
Discuz搭建付费阅读下载功能的方法
搭建discuz的付费阅读和下载功能可以通过以下步骤实现:1.安装并启用“discuz!付费阅读插件”,在后台设置帖子为付费阅读。2.安装并启用“discuz!付费下载插件”,在后台设置附件为付费下载。
Discuz开发微信小程序流程和框架选择
1. 分析Discuz功能,确定小程序实现的功能;2. 选择uni-app框架,因其跨平台兼容性、丰富组件库和强大社区支持;3. 注意数据同步、用户体验和性能优化;4. 灵活解决如权限系统等挑战。
相关源码
-
帝国cms题库问答学习平台模板知识付费网站源码+数据采集为教育机构、培训平台及在线学习场景设计,提供完整的题库管理与问答服务解决方案。支持多种题型展示与答案查询,满足不同层次的学习需求。查看源码 -
(自适应)帝国cms7.5模板新闻资讯门户带会员中心基于帝国CMS7.5内核开发的HTML5响应式模板,为新闻机构、媒体门户及资讯聚合平台设计。通过模块化布局实现图文混排查看源码 -
(自适应响应式)pbootcms紫色美容整形机构企业模板下载基于PbootCMS内核开发的响应式网站模板,为医疗美容机构、整形医院等企业设计,提供完整的线上展示平台采用紫色系配色方案,整体风格专业大气。模板包含首页轮播、服务项目、专家团队、案例展示等核心模块,能够充分展示医疗美容机构的专业服务和特色优势。查看源码 -
(PC+WAP)激光水幕音乐喷泉设备工程网站源码下载本模板基于PbootCMS系统开发,为喷泉设备工程类企业设计,特别适合展示音乐喷泉、激光水幕等水景艺术项目。采用响应式技术,确保各类工程案例在不同设备上都能呈现视觉效果。查看源码 -
帝国CMS中小学生知识点试题练习题考试源码下载基于帝国CMS后台管理系统,支持在线修改联系信息、网站参数等配置,操作流程简洁明了。专注于中小学教育领域,集成知识点总结、试题练习、考试资讯等学习资源,为师生提供全面的在线学习支持与服务。查看源码 -
(自适应响应式)黑色LED显示屏户外广告屏网站源码下载这是一款基于PbootCMS内核开发的响应式网站模板,专门为LED显示屏及户外广告行业打造。模板适配各类显示设备,帮助企业快速搭建专业官网,展示产品与服务优势,有效提升品牌形象。查看源码
| 分享笔记 (共有 篇笔记) |
