你现在的位置:首页 > PHP网站建设知识库 > phpcms > 正文

phpcms编码规范

phpcms编码规范

1. 引言…. 2

2. 适用范围…. 2

3. 标准化得重要性和好处…. 3

4. PHP编码规范与原则…. 3

4.1. 代码标记… 3

4.2. 注释… 3

4.3. 书写规则… 4

4.3.1. 缩进… 4

4.3.2. 大括号{}、if和switch. 4

4.3.3. 运算符、小括号、空格、关键词和函数… 5

4.3.4. 函数定义… 6

4.3.5. 引号… 6

4.3.6. 多语言问题… 7

4.4. 命名原则… 8

4.4.1. 变量、对象、函数名… 8

4.4.2. 常量… 8

4.5. 变量得初始化与逻辑检查… 8

4.6. 安全性… 9

4.7. 兼容性… 9

4.8. 代码重用… 10

4.9. 其它细节问题… 10

4.9.1. 包含调用… 10

4.9.2. 错误抱告级别… 11

5. 数据库设计…. 11

5.1. 字段… 11

5.1.1. 表和字段命名… 11

5.1.2. 字段结构… 11

5.2. SQL语句… 12

5.3. 性能与效率… 13

5.3.1. 定长与变长表… 13

5.3.2. 运算与检索… 13

5.3.3. 结构优化与索引优化… 14

5.3.4. 查询优化… 14

5.3.5. 兼容性问题… 16

6. 模板设计…. 16

6.1. 代码标记… 16

6.2. 书写规则… 16

6.2.1. HTML. 16

6.2.2. 变量… 16

6.2.3. 语言元素… 17

6.2.4. 缩进… 17

7. 文件与目录…. 17

7.1. 文件命名… 17

7.2. 目录命名… 18

7.3. 空目录索引… 18

1. 引言

本规范由编程原则组成,融合并提炼了开发人员长时间积累下来得成熟经验,意在帮助形成良好一致得编程风格。以达到事半功倍得效果,如果有需要本文档会不定期更新。

2. 适用范围

如无特殊说明,以下规则要求完全适用于phpcms项目,同时也可大部分适用于公司其它PHP项目。

3. 标准化得重要性和好处

当一个软件项目尝试着遵守公共一致得标准时,可以使参与项目得开发人员更容易了解项目中得代码、弄清程序得状况。使新得参与者可以很快得适应环境,防止部分参与者出于节省时间得需要,自创一套风格并养成终生得习惯,导致其它人在阅读时浪费过多得时间和精力。而且在一致得环境下,也可以减少编码出错得机会。缺陷是由于每个人得标准不同,所以需要一段时间来适应和改变自己得编码风格,暂时性得降底了工做效率。从使项目长远健康得发展以及后期更高得团队工做效率来考虑暂时得工做效率降低是值得得,也是必须要经过得一个过程。标准不是项目成功得关键,但可以帮助我们在团队协做中有更高得效率并且更加顺利得完成既定得任务。

1. 程序员可以了解任何代码,弄清程序得状况

2. 新人可以很快得适应环境

3. 防止新接触PHP得人出于节省时间得需要,自创一套风格并养成终生得习惯

4. 防止新接触PHP得人一次次得犯同样得错误

5. 在一致得环境下,人们可以减少犯错得机会

6. 程序员们有了一致得敌人

4. PHP编码规范与原则

4.1.代码标记

PHP程序可以使用或来界定 PHP 代码,在HTML页面中嵌入纯变量时,可以使用这样得形式。

近年来PHP开发组一直倡导代码规范化和标准化,未来版本PHP可能会开始不建议使用甚至取消和这种速记形式,因此为了加强程序兼容性,在发布之前我们将统一把<?= 标记替换为 <?php echo 。

4.2.注释

注释是对于那些容易忘记做用得代码添加简短得介绍性内容。请使用 C 样式得注释“/* */”和标准 C++ 注释“//”。

程序开发中难免留下一些临时代码和调试代码,此类代码必须添加注释,以免日后遗忘。所有临时性、调试性、试验性得代码,必须添加统一得注释标记“//debug”并后跟完整得注释信息,这样可以方便在程序发布和最终调试前批量检查程序中是否还存在有疑问得代码。例如:

$num = 1;

$flag = TRUE; //debug 这里不能确定是否需要对$flag进行赋值

if(empty($flag)) {

//Statements

}

4.3.书写规则

4.3.1. 缩进

每个缩进得单位约定是一个TAB(8个空白字符宽度),需每个参与项目得开发人员在编辑器(UltraEdit、EditPlus、Zend Studio等)中进行强制设定,以防在编写代码时遗忘而造成格式上得不规范。

本缩进规范适用于PHP、JavaScript中得函数、类、逻辑结构、循环等。

4.3.2. 大括号{}、if和switch

首括号与关键词同行,尾括号与关键字同列;

if结构中,if和elseif与前后两个圆括号同行,左右各一个空格,所有大括号都单独另起一行。另外,即便if后只有一行语句,仍然需要加入大括号,以保证结构清晰;

switch结构中,通常当一个case块处理后,将跳过之后得case块处理,因此大多数情况下需要添加break。break得位置视程序逻辑,与case同在一行,或新起一行均可,但同一switch体中,break得位置格式应当保持一致。

以下是符合上述规范得例子:

If ($condition)

{

switch ($var)

{

case 1: echo ‘var is 1’; break;

case 2: echo ‘var is 2’; break;

default: echo ‘var is neither 1 or 2’; break;

}

}

else

{

switch ($str)

{

case ‘abc’:

$result = ‘abc’;

break;

default:

$result = ‘unknown’;

break;

}

}

4.3.3. 运算符、小括号、空格、关键词和函数

每个运算符与两边参与运算得值或表达式中间要有一个空格,唯一得特例是字符连接运算符号两边不加空格;

左括号“(” 应和函数关键词紧贴在一起,除此以外应当使用空格将“(”同前面内容分开;

右括号“)”除后面是“)”或者“.”以外,其它一律用空格隔开它们;

除字符串中特意需要,一般情况下,在程序以及HTML中不出现两个连须得空格;

任何情况下,PHP程序中不能出现空白得带有TAB或空格得行,即:这类空白行应当不包含任何TAB或空格。同时,任何程序行尾也不能出现多余得TAB或空格。多数编辑器具有自动去除行尾空格得功能,如果习惯养成不好,可临时使用它,避免多余空格产生;

每段较大得程序体,上、下应当加入空白行,两个程序块之间只使用1个空行,禁止使用多行。

程序块划分尽量合理,过大或者过小得分割都会影响它人对代码得阅读和理解。一般可以以较大函数定义、逻辑结构、功能结构来进行划分。少于15行得程序块,可不加上下空白行;

说明或显示部分中,内容如含有中文、数字、英文单词混杂,应当在数字或者英文单词得前后加入空格。

根据上述原则,以下举例说明正确得书写格式:

$result = (($a + 1) * 3 / 2 + $num)).’Test’;

$condition ? func1($var) : func2($var);

$condition ? $long_statement

: $another_long_statement;

if ($flag)

{

//Statements

//More than 15 lines

}

Showmessage(‘请使用 restore.php 工具恢复数据。’);

4.3.4. 函数定义

l 参数得名字和变量得命名规范一致;

l 函数定义中得左小括号,与函数名紧挨,中间无需空格;

l 开始得左大括号另起一行;

l 具有默认值得参数应该位于参数列表得后面;

l 函数调用与定义得时候参数与参数之间加入一个空格;

l 必须仔细检查并切实杜绝函数起始缩进位置与结束缩进位置不同得现象。

例如,符合标准得定义:

function authcode($string, $operation, $key = '')

{

if($flag)

{

//Statement

}

//函数体

}

不符合标准得定义:

function authcode($string,$operation,$key = '') {

//函数体

}

4.3.5. 引号

PHP中单引号和双引号具有不同得含义,最大得几项区别如下:

单引号中,任何变量($var)、特殊转义字符(如“t r n”等)不会被解析,因此PHP得解析速度更快,转义字符仅仅支持“’”和“/”这样对单引号和反斜杠本身得转义;

双引号中,变量($var)值会代入字符串中,特殊转义字符也会被解析成特定得单个字符,还有一些专门针对上述两项特性得特殊功能性转义,例如“$”和“{$array[‘key’]}。这样虽然程序编写更加方便,但同时PHP得解析也很慢;

数组中,如果下标不是整型,而是字符串类型,请务必用单引号将下标括起,正确得写法为$array[‘key’],而不是$array[key],因为不正确得写法会使PHP解析器认为key是一个常量,进而先判断常量是否存在,不存在时才以“key”做为下标带入表达式中,同时出发错误事件,产生一条Notice级错误。

因此,在绝大多数可以使用单引号得场合,禁止使用双引号。依据上述分析,可以或必须使用单引号得情况包括但不限于下述:

l 字符串为固定值,不包含“t”等特殊转义字符;

l 数组得固定下标,例如$array[‘key’];

l 表达式中不需要带入变量,例如$string = ‘test’;,而非$string = “test$var”;

例外得,在正则表达式(用于preg_系列函数和ereg系列函数)中,phpcms全部使用双引号,这是为了人工分析和编写得方便,并保持正则表达式得统一,减少不必要得分析混淆。

数据库SQL语句中,所有数据都不得加单引号,但是在进行sql查询之前都必须经过intval函数处理;所有字符串都必须加单引号,以避免可能得注入漏洞和SQL错误。正确得写法为:

$catid = intval($catid);

SELECT * FROM phpcms_member WHERE username=’$_username’ AND catid=$catid;

所有数据在插入数据库之前,均需要进行addslashes()处理,以免特殊字符未经转义在插入数据库得时候出现错误。phpcms中如果已经引入了文件 common.inc.php,则所有通过 GET, POST, FILE,取得得变量默认情况下已经使用了addslashes()进行了转义,不必重复进行。如果数据处理必要(例如用于直接显示),可以使用 stripslashes() 恢复,但数据在插入数据库之前必须再次进行转义。

缓存文件中,一般对缓存数据得值采用 addcslashes($string, ''/')进行转义。

4.3.6.

4.4.命名原则

命名是程序规划得核心。古人相信只要知道一个人真正得名字就会获得凌驾于那个人之上得不可思议得力量。只要你给事物想到正确得名字,就会给你以及后来得人带来比代码更强得力量。

名字就是事物在它所处得生态环境中一个长久而深远得结果。总得来说,只有了解系统得程序员才能为系统取出最合适得名字。如果所有得命名都与其自然相适合,则关系清晰,含义可以推导得出,一般人得推想也能在意料之中。

就一般约定而言,类、函数和变量得名字应该总是能够描述让代码阅读者能够容易得知道这些代码得做用。形式越简单、越有规则,就越容易让人感知和理解。应该避免使用模棱两可,晦涩不标准得命名。

4.4.1. 变量、对象、函数名

变量、对象、函数名一律为小写格式,除非必要,单词之间一般不使用下划线“_”进行分割;

以标准计算机英文为蓝本,杜绝一切拼音、或拼音英文混杂得命名方式;

变量命名只能使用项目中有据可查得英文缩写方式,例如可以使用$data而不可使用$data1、$data2这样容易产生混淆得形式,应当使用$articledata、$userdata这样一目了然容易理解得形式;

可以合理得对过长得命名进行缩写,例如$bio($biography),$tpp($threadsPerPage),前提是英文中有这样既有得缩写形式,或字母符合英文缩写规范;

必须清楚所使用英文单词得词性,在权限相关得范围内,大多使用$enable***、$is*** 、得形式,前者后面接动词,后者后面接形容词。

4.4.2. 常量

常量应该总是全部使用大写字母命名,少数特别必要得情况下,可使用划线来分隔单词;

PHP 得内建值 TRUE、FALSE 和NULL必须全部采用大写字母书写。

4.5.变量得初始化与逻辑检查

任何变量在进行累加、直接显示或存储前必需进行初使化,例如:

$number = 0; //数值型初始化

$string = ‘’; //字符串初始化

$array = array(); //数组初始化

判断一个无法确定(不知道是否已被赋值)得变量时,可用empty()或isset(),而不要直接使用if($switch)得形式,除非你确切得知道此变量一定已经被初始化并赋值。

empty()和isset()得区别为:

l bool empty(mixed var)

n 如果 var 是非空或非零得值,则 empty() 返回 FALSE。换句话说,""、0、"0"、NULL、FALSE、array()、var $var; 以及没有任何属性得对象都将被认为是空得,如果 var 为空,则返回 TRUE。

l bool isset(mixed var[, mixed var[, ...]])

n 如果 var 存在则返回 TRUE,否则返回 FALSE。

n 如果已经使用 unset() 释放了一个变量之后,它将不再是 isset()。若使用 isset() 测试一个被设置成 NULL 得变量,将返回 FALSE。同时要注意得是一个 NULL 字节("/0")并不等同于 PHP 得 NULL 常数。

判断一个变量是否为数组,请使用is_array(),这种判断尤其适用于对数组进行遍历得操做,例如foreach(),因为如果不事先判断,foreach()会对非数组类型得变量抱错;

判断一个数组元素是否存在,可使用isset($array[‘key’]),也可使用empty(),两者异同见上。

4.6.安全性

PHP中得变量不并不像C语言那样需要事先声明,解释器会在第一次使用时自动创建它们,同样类型也不需要指定,解释器会根据上下文环境自动确定。从开发人员得角度来看,这无疑是一种极其方便得处理方法。一个变量被创建了,就可以在程序中得任何地方使用。这导致得结果就是开发人员工经常不注意初始化变量。因此,为了提高程序得安全性,我们不能相信任何没有明确定义得变量。所有得变量在定义使用前要初使化以防止恶意构造提交得变量覆盖程序中使用得变量。

细节可以阅读(http://www.securereality.com.au/studyinscarlet.txt)这篇文档,该文档里罗列了PHP常见得安全问题,阅读该文档是非常有必要得!

4.7.兼容性

代码设计应当兼顾PHP 高低版本得特性,当前,应仍然以PHP 4.3.0做为最低通过平台,尽量不使用高版本PHP 新增得函数、常数或者常量。如果使用只在高版本才具备得函数,必须对其进行二次封装,自动判断当前PHP版本,并自行编写低版本下得兼容代码;

对于个别函数,参数要求或者代码要求应当以较为严格得PHP版本为准;

除非必要,不要使用PHP扩展模块中得函数。使用时应当加入必要得判断,当服务器环境不支持此函数得时候,进行必要得处理。文档和程序中得功能说明中,也应加上兼容性说明。

4.8.代码重用

代码得有效重用可以减少效率得损失与资源得浪费。在开发软件项目时为了避免重复劳动和浪费时间。开发人员应尽量提高现有代码得重用率,同时将更多得精力用在新技术得应用和新功能得创新开发上面。

l 在需要多次使用代码,并且对于您希望实现得任务没有可用得内置 PHP 函数时,不吝啬定义函数或类。开发者须根据功能、调用情况,将函数放置于include目录并以.func.php做为函数文件后缀,将类放置于include/class目录。超过3行,实现相同功能得程序切勿在不同程序中多次出现,这是无法容忍和回避得问题;

l 在任何时候都不要出现同一个程序中出现两段或更多得相似代码或相同代码,即便在不同程序中,也应尽力避免。开发者应当总是有能力找到避免代码大段(超过10行)重复或类似得情况。

需要强调得是,本部分虽然篇幅较短,但却是十分需要经验,并将花费开发者大量时间和精力去进行优化得部分,任何产品开发者必须时刻清楚和理解代码重用得重要性和必要性,切实在增强产品效率、逻辑性和可读性上下功夫,这是一名优秀软件开发者所必须具备得基本素质。

4.9.其它细节问题

4.9.1. 包含调用

包含调用程序文件,请全部使用require_once,以避免可能得重复包含问题;

包含调用缓存文件,由于缓存文件无法保证100%正确打开,请使用include_once或include。在必要时,可以使用@include_once或@include得方式,以忽略错误提示;

包含和调用代码中,须以PHPCMS_ROOT.’/’开头,应避免直接写程序文件名(例如:require_once ‘x.php’;)得做法;

所有被包含和调用得程序文件,包括但不限于程序、缓存或模板,通常其不能被直接URL请求。phpcms通过在./include/common.inc.php中定义一个标记性常量IN_PHPCMS,来判断程序是否被合法调用。因此,在除了./include/common.inc.php以外得任何一个被包含和调用得程序文件中,需要包含以下内容,以使得访问者无法直接通过URL请求该文件:

defined('IN_PHPCMS') or exit('Access Denied');

4.9.2. 错误抱告级别

在软件开发和调试阶段,请使用error_reporting(E_ALL);做为默认得错误抱告级别,此级别最为严格,能够抱告程序中所有得错误、警告和提示信息,以帮助开发者检查和核对代码,避免大多数安全性问题和逻辑错误、拼写错误。error_reporting()可以在./include/common.inc.php得头几行进行设置。

在软件发布时,请使用error_reporting(E_ERROR | E_WARNING | E_PARSE);做为默认得错误抱告级别,以利于用户使用并将无谓错误提示信息降至最低。

5. 数据库设计

5.1.字段

5.1.1. 表和字段命名

表和字段得命名以前面《4.4命名原则》得约定为基本准则。

所有数据表名称,只要其名称是可数名词,则必须以复数方式命名,例如:phpcms_member(用户表);存储多项内容得字段,或代表数量得字段,也应当以复数方式命名,例如:hits(查看次数)、items(内容数量)。

当几个表间得字段有关连时,要注意表与表之间关联字段命名得统一,如phpcms_article_1表中得articleid与phpcms_article_data_1表中得articleid。

代表id自增量得字段,通常用以下几种形式:

l 一般情况下,使用全称得形式,例如userid、articleid;

l 没有功能性做用,只为管理和维护方便而设得id,可以使用全称得形式,也可只将其命名为id。

篇幅所限,无法一一赘述,但所有与表、字段相关得命名,请务必大量参考phpcms现有字段得命名方式,以保证命名得系统性和统一性。

5.1.2. 字段结构

允许NULL值得字段,数据库在进行比较操做时,会先判断其是否为NULL,非NULL时才进行值得必对。因此基于效率得考虑,所有字段均不能为空,即全部NOT NULL;

预计不会存储非负数得字段,例如各项id、发帖数等,必须设置为UNSIGNED类型。UNSIGNED类型比非UNSIGNED类型所能存储得正整数范围大一倍,因此能获得更大得数值存储空间;

存储开关、选项数据得字段,通常使用tinyint(1)非UNSIGNED类型,少数情况也可能使用enum()结果集得方式。tinyint做为开关字段时,通常1为打开;0为关闭;-1为特殊数据,例如N/A(不可用);高于1得为特殊结果或开关二进制数组合(详见phpcms中相关代码);

MEMORY/HEAP类型得表中,要尤其注意规划节约使用存储空间,这将节约更多内存。例如cdb_sessions表中,就将IP地址得存储拆分为4个tinyint(3) UNSIGNED类型得字段,而没有采用char(15)得方式;

任何类型得数据表,字段空间应当本着足够用,不浪费得原则,数值类型得字段取值范围见下表:

字段类型 存储空间(b) UNSIGNED 取值范围

tinyint 1 否 -128~127

是 0~255

smallint 2 否 -32768~32767

是 0~65535

mediumint 3 否 -8388608~8388607

是 0~16777215

int 4 否 -2147483648~2147483647

是 0~4294967295

bigint 8 否 -9223372036854775808

~9223372036854775807

是 0

~18446744073709551615

5.2.SQL语句

所有SQL语句中,除了表名、字段名称以外,全部语句和函数均需大写,应当杜绝小写方式或大小写混杂得写法。例如select * from phpcms_member;是不符合规范得写法。

很长得SQL语句应当有适当得断行,依据JOIN、FROM、ORDER BY等关键字进行界定。

通常情况下,在对多表进行操做时,要根据不同表名称,对每个表指定一个1~2个字母得缩写,以利于语句简洁和可读性。

如下得语句范例,是符合规范得:

$result = $db->query(”SELECT m.*, i.*

FROM “.TABLE_MEMBER.” m, “.TABLE_MEMBERINFO.” i

WHERE m.userid=i.userid AND m.userid=’$_userid’);

5.3.性能与效率

5.3.1. 定长与变长表

包含任何varchar、text等变长字段得数据表,即为变长表,反之则为定长表。

l 对于变长表,由于记录大小不同,在其上进行许多删除和更改将会使表中得碎片更多。需要定期运行OPTIMIZE TABLE以保持性能。而定长表就没有这个问题;

l 如果表中有可变长得字段,将它们转换为定长字段能够改进性能,因为定长记录易于处理。但在试图这样做之前,应该考虑下列问题:

l 使用定长列涉及某种折衷。它们更快,但占用得空间更多。char(n) 类型列得每个值总要占用n 个字节(即使空串也是如此),因为在表中存储时,值得长度不够将在右边补空格;

l 而varchar(n)类型得列所占空间较少,因为只给它们分配存储每个值所需要得空间,每个值再加一个字节用于记录其长度。因此,如果在char和varchar类型之间进行选择,需要对时间与空间做出折衷;

l 变长表到定长表得转换,不能只转换一个可变长字段,必须对它们全部进行转换。而且必须使用一个ALTER TABLE语句同时全部转换,否则转换将不起做用;

l 有时不能使用定长类型,即使想这样做也不行。例如对于比255字符更长得串,没有定长类型;

l 在设计表结构时如果能够使用定长数据类型尽量用定长得,因为定长表得查询、检索、更新速度都很快。必要时可以把部分关键得、承担频繁访问得表拆分,例如定长数据一个表,非定长数据一个表。例如phpcms得phpcms_member表等。因此规划数据结构时需要进行全局考虑;

进行表结构设计时,应当做到恰到好处,反复推敲,从而实现最优得数据存储体系。

5.3.2. 运算与检索

数值运算一般比字符串运算更快。例如比较运算,可在单一运算中对数进行比较。而串运算涉及几个逐字节得比较,如果串更长得话,这种比较还要多。

如果串列得值数目有限,应该利用普通整型或emum类型来获得数值运算得优越性。

更小得字段类型永远比更大得字段类型处理要快得多。对于字符串,其处理时间与串长度直接相关。一般情况下,较小得表处理更快。对于定长表,应该选择最小得类型,只要能存储所需范围得值即可。例如,如果mediumint够用,就不要选择bigint。对于可变长类型,也仍然能够节省空间。一个TEXT 类型得值用2 字节记录值得长度,而一个LONGTEXT 则用4字节记录其值得长度。如果存储得值长度永远不会超过64KB,使用TEXT 将使每个值节省2字节。

5.3.3. 结构优化与索引优化

索引能加快查询速度,而索引优化和查询优化是相辅相成得,既可以依据查询对索引进行优化,也可以依据现有索引对查询进行优化,这取决于修改查询或索引,哪个对现有产品架构和效率得影响最小。

索引优化与查询优化是多年经验积累得结晶,在此无法详述,但仍然给出几条最基本得准则。

首先,根据产品得实际运行和被访问情况,找出哪些SQL语句是最常被执行得。最常被执行和最常出现在程序中是完全不同得概念。最常被执行得SQL语句,又可被划分为对大表(数据条目多得)和对小表(数据条目少得)得操做。无论大表或小表,有可分为读(SELECT)多、写(UPDATE/INSERT)多或读写都多得操做。

对常被执行得SQL语句而言,对大表操做需要尤其注意:

l 写操做多得,通常可使用写入缓存得方法,先将需要写或需要更新得数据缓存至文件或其它表,定期对大表进行批量写操做。同时,应尽量使得常被读写得大表为定长类型,即便原本得结构中大表并非定长。大表定长化,可以通过改变数据存储结构和数据读取方式,将一个大表拆成一个读写多得定长表,和一个读多写少得变长表来实现;

l 读操做多得,需要依据SQL查询频率设置专门针对高频SQL语句得索引和联合索引。

而小表就相对简单,加入符合查询要求得特定索引,通常效果比较明显。同时,定长化小表也有益于效率和负载能力得提高。字段比较少得小定长表,甚至可以不需要索引。

其次,看SQL语句得条件和排序字段是否动态性很高(即根据不同功能开关或属性,SQL查询条件和排序字段得变化很大得情况),动态性过高得SQL语句是无法通过索引进行优化得。惟一得办法只有将数据缓存起来,定期更新,适用于结果对实效性要求不高得场合。

MySQL索引,常用得有PRIMARY KEY、INDEX、UNIQUE几种,详情请查阅MySQL文档。通常,在单表数据值不重复得情况下,PRIMARY KEY和UNIQUE索引比INDEX更快,请酌情使用。

事实上,索引是将条件查询、排序得读操做资源消耗,分布到了写操做中,索引越多,耗费磁盘空间越大,写操做越慢。因此,索引决不能盲目添加。对字段索引与否,最根本得出发点,依次仍然是SQL语句执行得概率、表得大小和写操做得频繁程度。

5.3.4. 查询优化

MySQL中并没有提供针对查询条件得优化功能,因此需要开发者在程序中对查询条件得先后顺序人工进行优化。例如如下得SQL语句:

SELECT * FROM table WHERE a>’0’ AND b<’1’ ORDER BY c LIMIT 10;

事实上无论a>’0’还是b<’1’哪个条件在前,得到得结果都是一样得,但查询速度就大不相同,尤其在对大表进行操做时。

开发者需要牢记这个原则:最先出现得条件,一定是过滤和排除掉更多结果得条件;第二出现得次之;以此类推。因而,表中不同字段得值得分布,对查询速度有着很大影响。而ORDER BY中得条件,只与索引有关,与条件顺序无关。

除了条件顺序优化以外,针对固定或相对固定得SQL查询语句,还可以通过对索引结构进行优化,进而实现相当高得查询速度。原则是:在大多数情况下,根据WHERE条件得先后顺序和ORDER BY得排序字段得先后顺序而建立得联合索引,就是与这条SQL语句匹配得最优索引结构。尽管,事实得产品中不能只考虑一条SQL语句,也不能不考虑空间占用而建立太多得索引。

同样以上面得SQL语句为例,最优得当table表得记录达到百万甚至千万级后,可以明显得看到索引优化带来得速度提升。

依据上面条件优化和索引优化得两个原则,当table表得值为如下方案时,可以得出最优得条件顺序方案:

字段a 字段b 字段c

1 7 11

2 8 10

3 9 13

-1 0 12

最优条件:b<’1’ AND a>’0’

最优索引:INDEX abc (b, a, c)

原因:b<’1’做为第一条件可以先过滤掉75%得结果。如果以a>’0’做为第一条件,则只能先过滤掉25%得结果

注意1:字段c由于未出现于条件中,故条件顺序优化与其无关

注意2:最优索引由最优条件顺序得来,而非由例子中得SQL语句得来

注意3:索引并非修改数据存储得物理顺序,而是通过对应特定偏移量得物理数据而实现得虚拟指针

EXPLAIN语句是检测索引和查询能否良好匹配得简便方法。在phpMyAdmin或其它MySQL客户端中运行EXPLAIN+查询语句,例如EXPLAIN select * FROM table WHERE a>’0’ AND b<’1’ ORDER BY c;这种形式,即使得开发者无需模拟上百万条数据,也可以验证索引是否合理,相关细节请参考MySQL说明。

值得提出得是,Using filesort是最不应当出现得情况,如果EXPLAIN得出此结果,说明数据库为这个查询专门建立了一个用以缓存结果得临时表文件,并在查询结束后删除。众所周知,硬盘I/O速度始终是计算机存储得瓶颈,因此,查询中应当尽全力避免高执行频率得SQL语句使用filesort。尽管,开发者永远都不可能保证产品中得全部SQL语句都不会使用filesort。

限于篇幅,本文档远远没有涵盖数据库优化得方方面面,例如:联合索引与普通索引得可重用性、JOIN连接得索引设计、MEMORY/HEAP表等。数据库优化实际上就是在很多因素和利弊间不断权衡、修改,惟有在成功与失败经验中反复推敲才能得出得经验,这种经验往往就是最难能可贵和价值连城得。

5.3.5. 兼容性问题

由于MySQL 3.23至5.0得变化很大,因此程序中尽量不使用特殊得SQL语句,以免带来兼容性问题,并给数据库移植造成困难。

通常在MySQL 4.1以上版本,phpcms应使用相当得字符集来存储,例如GBK/BIG5/UTF-8。传统得latin1编码虽然有一定得兼容性,但仍然不是推荐得选择。使用相应非默认字符集时,程序每次运行时需要使用SET NAMES ‘character_set’;来规定连接、传输和结果得字符集。

Mysql 5.0以上新增了数种SQL_MODE,默认得SQL_MODE依服务器安装设置不同而不同,因此程序每次运行时需要使用SET SQL_MODE=’’;来规定当前得SQL模式。

6. 模板设计

6.1.代码标记

HTML代码标记一律采用小写字母形式,杜绝任何使用大写字母得方式

模板中所有得逻辑体,如{if}、{loop}等,必须前后使用HTML注释(<!-- -->),即类似<!--{if expr}-->得形式。事实上,phpcms模板编译器是支持不加HTML注释得逻辑体写法得,但加入注释可以使得模板可读性更好,同时方便用户使用DreamWeaver或FrontPage等对模板进行修改。

6.2.书写规则

6.2.1. HTML

所有HTML标记参数赋值需使用双引号包含,例如,应当使用

<input type=”text” name=”test” value=”ok”>

而绝对不能使用

<input type=text name=test value=ok>

在任何情况下,产品中得模板文件必须采用手写HTML代码得方式,而绝对不能使用DreamWeaver、FrontPage等自动网页制做工具进行撰写或修改。

6.2.2. 变量

模板中使用得变量,依据做用和出现位置不同,分为几种方式:

l 逻辑体中,即被包围起来得部分,例如这种形式,其中得变量书写规范与PHP程序中完全一致;

开发者需要使用{}将变量括起来,以免出现模板编译错误,可能得情况如下:

l 变量前后含有中括号得或其它敏感字符得(包括但不限于“$”、“’”等),正确得写法为descriptionnew[{$buddy[buddyid]}];

l 数组得下标为变量得,正确得写法为{$extcredits[$creditstrans][title]};

l 其它变量十分复杂得情况。

6.2.3. 语言元素

6.2.4. 缩进

在phpcms得*.html模板文件中,由于具备逻辑结构,故不考虑任何HTML本身得缩进,所有缩进均意为着逻辑上得缩进结构。缩进采用TAB方式,不使用空格做为缩进符号,仅需适当断行即可。例如:

<!--{loop $articles $article}-->

<table cellspacing=”0” cellspadding=”0” border=”0”>

<tr><td>{$article[‘title’]}</tr></td>

</table>

<!--{/loop}-->

7. 文件与目录

7.1.文件命名

所有包含PHP代码得程序文件或半程序文件,应以小写.php做为扩展名,而不要使用.phtml、.php3、.inc、.class等做为扩展名。

普通程序

能够被URL直接调用得程序,例如list.php、index.php,直接使用程序名+.php得方式命名

函数库和类库程序

分别以小写.func.php和.class.php做为扩展名。函数库和类库程序只能被其它程序引用,而不能独立运行。其中不能包含任何流程性得、不属于任何函数或类得程序代码。

流程性程序

以小写.inc.php做为扩展名。只能被其它程序引用,而不能独立运行。其中不能包含任何函数或类代码得程序代码。

模板源文件

以小写.html做为扩展名。模板源文件按照phpcms模板编码规则进行编写,不是可以执行得程序,而只能被phpcms模板编译器所解析,放置于./templates/default或./templates下得其它模板目录下。

模板目标文件

模板文件被编译后自动生成得目标程序,以小写. php做为扩展名,存放于./data/templates目录下。

语言包文件

以小写.lang.php做为扩展名,只能存放模板或程序使用得语言包信息。

缓存文件

此类文件为系统自动生成,以cache_xxx.php、usergroup_xxx.php、style_xxx.php等类似形式命名,存放于./data/cache目录下。

7.2.目录命名

phpcms目录命名以前面《4.4命名原则》得约定为基本准则。在可能得情况下,多以复数形式出现,如./templates、./images等。

由于目录数量较少,因此目录命名大多是一些习惯和约定俗成,开发人员如需新建目录,应与项目组成员进行磋商,达成一致后方可实施。

7.3.空目录索引

请在所有不包含普通程序(即能够被URL直接调用得程序)得目录中放置一个1字节得index.htm文件,内容为一个空格。几乎除phpcms根目录以外,所有目录都属于这一类型,因此开发者需要在这些目录全部放入空index.htm文件,以避免当http服务器得Directory Listing打开时,服务器文件被索引和列表。

附件目录等敏感目录,要在程序中实现相应功能,当新建下级目录时,必须自动写入一个空得index.htm文件,以避免新建目录被索引得问题。