现在大部分网站后台程序都采用了Model-View-Control架构,数据、前端界面和逻辑控制相分离,开发速度更加高效。同时将动态页面静态化,部分程度上缓解了服务器的请求。本文主要是为了最近在Discuz系统上做的一个二次开发,然后写下自己对dz系统的理解。
相关概念
这也是我第一次接触Discuz系统,先说说我感触最深的两点,一是MVC架构,二是动态页面静态化。
我们先接触一下MVC框架是什么样子的,然后再去简单剖析一下Discuz系统的渲染流程。形象理解一下Model负责获取整理数据,View负责将取得的数据组织、美化,并最终向用户终端输出,而Controller主要作为一个M和V的桥梁,负责将M产生的数据交给V去显示。
整个工作流程如下图:
实现了数据和模板视图的隔离,两者通过Controller进行连接。
接下来说一下PHP页面静态化,先看一下概念解释:
PHP静态化分为:纯静态化 和 伪静态化;纯静态化又分为:局部静态化 和 完全静态化
纯静态化:是把PHP生成的动态页面保存成静态的html文件,用户访问该静态页面,而不是用户每一次访问都重新生成一张相同的网页,优点就是减小服务器开销,
局部静态化:是生成的静态文件中,有局部的数据还是通过ajax技术动态获取的;
完全静态化:即不存在动态获取数据的情况,所以内容都来自静态的html页面伪静态化:其实还是动态访问,其实质是动态生成数据,你访问的网址类似于
http://yourhost.com/index/post/12
,是一个静态地址,该地址多见于博客地址,但伪静态化中,你访问的网址实际上经过服务器解析,还是会解析成类似于http://yourhost.com/?c=index&a=post&id=12
的地址,所以称之为伪静态化
伪静态的优点:美观;便于搜索引擎收录
形象来说就是把不经常变动的数据一次动态获取之后写到静态的htm文件中,在允许的时间范围内就可以直接访问静态的htm文件,减小服务器的请求量,局部需要更新的数据可以采用ajax请求技术进行异步更新。
简单框架实现
这里简单实现了一个框架,代码目录结构如下:
/--
-- cache/
test_show_static.htm
-- libs/
-- Controller/
testController.class.php
-- Model/
testModel.class.php
-- View/
testView.class.php
function.php
index.php
index_cache.php
/
为html文件的根目录,cache目录下存储的是PHP页面静态化之后的静态htm文件,libs目录下是我们MVC架构的主要代码。function.php
放置一些常用函数,这里就简单实现了MVC分别对应的函数。index.php
没有PHP页面静态化的入口文件index_cache.php
添加了PHP页面静态化的入口文件
在框架下面写代码命名要非常规范,因为到底调用哪个控制器、数据、模板视图都是通过文件的名字去进行查找的,而且要放置在对应的目录下面。
到了该上代码的时间了orz,一个一个来贴吧。
test_show_static.htm这个文件是PHP页面静态化自动生成的htm数据。
testController.class.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 11:40:18
* @Last Modified by: root
* @Last Modified time: 2016-08-31 12:02:54
*/
class testController
{
function show()
{
$testModel = M('test');
$data = $testModel->get();
$testView = V('test');
$testView->display($data);
}
}
?>
testModel.class.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 11:40:05
* @Last Modified by: root
* @Last Modified time: 2016-08-31 11:42:47
*/
class testModel
{
function get()
{
return "v4if";
}
}
?>
testView.class.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 11:39:50
* @Last Modified by: root
* @Last Modified time: 2016-08-31 11:43:51
*/
class testView
{
function display($data)
{
echo $data;
}
}
?>
function.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 11:45:38
* @Last Modified by: root
* @Last Modified time: 2016-08-31 14:55:46
*/
function C($name, $method)
{
require_once('libs/Controller/'.$name.'Controller.class.php');
eval('$obj = new '.$name.'Controller();$obj ->'.$method.'();');
}
function M($name)
{
require_once('libs/Model/'.$name.'Model.class.php');
eval('$obj = new '.$name.'Model();');
return $obj;
}
function V($name)
{
require_once('libs/View/'.$name.'View.class.php');
eval('$obj = new '.$name.'View();');
return $obj;
}
?>
index.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 11:38:33
* @Last Modified by: root
* @Last Modified time: 2016-08-31 14:54:09
*/
error_reporting(E_ALL);
ini_set('display_errors','On');
//url形式 index.php?c=控制器名&m=方法名
require_once('function.php');
$controller = $_GET['c'];
$method = $_GET['m'];
C($controller, $method);
?>
index_cache.php文件:
<?php
/**
* @Author: v4if
* @Date: 2016-08-31 15:06:23
* @Last Modified by: root
* @Last Modified time: 2016-08-31 15:15:17
*/
error_reporting(E_ALL);
ini_set('display_errors','On');
//url形式 index.php?c=控制器名&m=方法名
$controller = $_GET['c'];
$method = $_GET['m'];
$static_tpl = 'cache/'.$controller.'_'.$method.'_static.htm';
if (is_file($static_tpl) && (time() - fileatime($static_tpl) < 1200)) {
require_once($static_tpl);
} else {
ob_start();
require_once('function.php');
C($controller, $method);
$html = ob_get_contents();
file_put_contents($static_tpl, $html);
}
?>
对Discuz的简单流程剖析
先列一下经常用到的几个比较重要的目录
/--
-- data/ 附件数据、数据库与文件缓存
-- source/ 程序模块功能处理目录
-- module/ 程序功能模块程序包
-- function/ DX自定义函数库
-- class/ 核心类库
-- template/ 模板目录
admin.php 后台入口文件
forum.php 论坛频道入口文件
index.php 首页
portal.php 门户入口文件
上面基本上都是我们经常需要改动测试的目录或文件。
在安装Discuz系统的时候需要注意一下X3.2不兼容PHP7的版本,如果PHP环境是7.0及以上的,请从这里下载兼容版本 discuz-x32-php7。还有就是对Discuz根目录赋予可读可写权限,linux下可以通过执行chmod -R 777 /var/www/html
命令即可。
接下来我们尝试跟踪一个具体的网址来看看Discuz的渲染流程,就以默认页面http://localhost/forum.php
主页为例。
这里需要明确一点,Discuz的入口地址是index.php文件,forum.php文件是index.php通过重定向然后访问到的。
然后打开fourm.php文件我们可以看到结尾有这样一句话:require DISCUZ_ROOT.'./source/module/forum/forum_'.$mod.'.php';
也就是说是通过传递进来的$mod参数决定我们将要调用的控制器页面,可以修改一下Discuz的源码,看看$mod参数具体是什么值,可以在require
前面加一句echo $mod;
将$mod的值输出到页面上,然后刷新页面可以看到输出的index
。
即接下来调用的是/source/module/forum/forum_index.php'
文件,可以看到在forum_index.php文件的433行有一个template的模板调用
继续跟踪下去我们可以找到template函数的声明文件,在/source/function/function_core.php
文件的519行可以看到template函数的定义
然后可以在template函数里面插入我们自己的输出语句,在function_core.php文件的630行插入echo 'v4if+'.$tplfile.'+v4if';
语句,看看具体调用了哪些模板文件进行的页面渲染,然后刷新页面可以看到页面输出内容:
v4if+./template/default/forum/discuz.htm+v4if
v4if+./template/default/common/header.htm+v4if
v4if+./template/default/common/header_userstatus.htm+v4if
v4if+./template/default/member/login_simple.htm+v4if
v4if+./template/default/common/footer.htm+v4if
到这里之后具体调用了哪些模板文件就一目了然了,可以根据自己的业务需求对相应的php或者htm文件进行修改。