Discuz开发 Discuz 2.5的新程序架构优化说明

[复制链接]
ARCHY明星会员实名认证 发表于 2012-9-10 11:55:34 [Discuz开发] 显示全部楼层 |阅读模式 上一主题 下一主题

马上注册,一起探讨正确快速的建站方法

您需要 登录 才可以下载或查看,没有帐号?快速注册

x
discuz! X2.5新版架构优化主要针对以下6个方面:一.程序底层架构的改进;二.用户输入数据的处理;三.数据库DB层的改进;四.内存级缓存层的优化;五.多服务器分库分布式部署;六.主要性能瓶颈点的优化。

程序底层架构

• 要求PHP版本大于5.1,抛弃了对PHP4的支持
• 大量使用了面向对象编程(OOP)
• 实现了程序运程过程中按需加载,按需加载主要是针对类文件
• 对目录名、文件名和类名的要求

类文件存在在/source/class 目录中,类名和文件名相同,一个类一个文件 类名以下划线(_)分隔,第一个下划线之前部分为目录名,没有下划线的类名直接放/source/class/目录下。

产品中个别特殊类由于历史原因无法实现自动加载,需手动处理 include或require

• class_core.php 流程控制的说明

Class_core.php是入口启动文件,主要实现了以下功能:

1、注册autoload方法和异常处理方法;
2、C::t方法的实现;
3、memory的初始化;
4、创建discuz_application实例(discuz_application是原来discuz! X2的discuz_core);
5、简写类的映射:

class C extends core {}
class DB extends discuz_database {}

• function_core.php 减肥之术

function_core.php是系统的核心函数库文件,随着系统功能的丰富,函数库越来越大,慢慢地变成了系统快速启动的负担,为此我们将function_core中的函数按功能拆分到不同的类文件中,实现程序的按需加载; 原有函数名保留不变,做相应类静态方法的映射,兼容产品和插件的用法。

具体做法是在source/class目录增加两个目录,helper和lib source/class/helper目录中的文件为函数的分类集合,类的静态方法,可直接使用不用实例化 source/class/lib目录中的文件为工具类的集合类文件,使用时需实例化

用户输入数据的处理

Discus! X2.5之前版本对$_GET和$_POST的值默认是进行addslashes处理,函数在使用此值时信任外部数据的安全性,但这样处理的弊端是容易生产二次注射的漏洞,为了防止此类漏洞的产生,函数必须不信任任何数据外部数据的安全性,为此我们做了以下的处理增强系统安全:

    $_GET和$_POST的值默认不做addslashes处理;
    $_GET为$_GET和$_POST数组的合并,代码中统一使用$_GET取值;
    $_G['gp_xx']的写法默认不再支持,config.php中有兼容开关;
  $_config['input']['compatible'] = 1;// $_GET|$_POST的兼容处理,0为关闭,
         1为开启;开启后即可使用$_G['gp_xx'](xx为变量名,$_GET和$_POST集合的所有变量 名),值为已经addslashes()处理过,兼容插件;

数据库DB层

• 原DB类的改进

Discuz! X2.5新版对数据库DB层进行了功能和安全方面的加强:

1、addslashes的处理

insert(),update(),delete()方法对传入其的数组形式的参数进行安全处理:intval或addslashes,字符串形式的参数将不处理,请注意

2、新添加的方法fetch_all($sql),order(), limit(),field()等方法,其中fetch_all方法以数组方式返回查询多条记录数据,且可以设置数据的KEY值使用某字段值

3、SQL语句format的支持

例:查询10个用户uid大于100的用户数据,以uid为返回结果数组的key
  1. $arr = DB::fetch_all(‘SELECT * FROM %t WHERE uid>%d LIMIT %d’, array(‘common_member’, ‘100’, ‘10’), ‘uid’);
复制代码
支持的fomat有:
  1. %t  DB::table()
  2. %d  intval()
  3. %s  addslashes()
  4. %n  in IN (1,2,3)
  5. %f  sprintf('%f', $var)
  6. %i  直接使用不进行处理
复制代码
4、返回值的处理

在非UNBUFFERED的情况下:
INSERT SQL语句返回insert_id()
UPDATE和DELETE SQL语句返回affected_rows()

• 新增数据层:数据层的规范和约定
    • 一个数据表一个class文件,以table_加上不带前缀的表名命名,尽量不操作其它表;
例:source/class/table/table_common_member.php
     • 不能使用$_G、$POST、$GET等全局变量;
    • 关联查询(JOIN)尽量拆分为单条查询,不能拆分的放入主表的类中;
    • 方法名以下划线分隔,全部为小写,全部为单数,直接返回结果,保留关键字:
      on、get、set, 方法参数不能以数组的形式传入,数据可以;
    • 除数据表文件以外,其它文件禁止出现SQL语句;
    • 查询结果返回一行记录方法名使用fetch开头,返回多行记录方法名使用fetch_all
      开头,查询中使用SQL语句count函数返回一个数值的使用count开头;
    • 方法名中by后面的是以下划线(_)分隔的表字段名,不要使用复数型,例如:
      fetch_all_by_uid()而不是fetch_all_by_uids();

    • 方法名需去掉表名,如:common_member表类方法
      fetch_member_by_username应命名为fetch_by_username;
    • 数据表类继承discuz_table基类,基类实现CURD操作,fetch方法实现了根据一个主键 值得到一行记录、fetch_all方法实现了根据一组主键值得到多行记录(二维数据,主  键值为 key)、count方法返回了表的总记录数据;
    • 如果表是无主键或是关联主键,则基类中的CURD将不能使用,需自己在相应的表类中实现, 同时将$this->_pk设置为空;
    • DB层封装的函数实现了addslashes,个别直接写sql语句的需主意addslashes;
    • 使用C::t('tablename')->method();调用;
    • C::t插件调用方式
  1. 表名:mytablename
  2. 目录:source/plugin/mypluginid/table/table_mytablename.php
  3. 类名:table_mytablename
  4. 用法:C::t('#mypluginid#mytablename')->method()
复制代码




上一篇:X2.5 升0901版本后无法输入验证码的解决方法
下一篇:Discuz!的插件流程、文件命名规范和class_core.php

大神点评5

我不服 发表于 2012-9-26 09:37:56 [Discuz开发] 显示全部楼层
回复那么多,没有加分。  
谷哥哥 发表于 2012-9-26 09:37:56 [Discuz开发] 显示全部楼层
厉害!强~~~~没的说了!  
快速跨越 发表于 2012-10-20 23:16:48 [Discuz开发] 显示全部楼层
路过了。
日观止 发表于 2012-11-25 13:05:05 [Discuz开发] 显示全部楼层
学习一下,谢谢分享
闪电007 发表于 2013-1-10 20:26:19 [Discuz开发] 显示全部楼层
      
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

快速回复 返回顶部 返回列表