良好的PHP编码规范能让你的代码看起来更加的优雅,清晰的结构有助于提高可读性并减少工作量。
Annuo最近在学习PHP框架,发现自己以前编写的代码一点都不规范,实在汗颜,特此贴上PHP编码规范,以示警醒。
以下内容部分总结自 Typecho PHP 编码规范 和 CodeIgniter 开发规范 ,可戳地址进行传送。
文件应该使用 Unicode (UTF-8) 编码保存,不要使用 字节序标记(BOM) 。与 UTF-16 和 UTF-32 不同,UTF-8 编码的文件不需要指明字节序,而且 字节序标记(BOM) 在PHP中会产生预期之外的输出,阻止了应用程序设置它自己的头信息。
如果保存带BOM的编码,会在文件头输出类似\ufeff
的内容。这样是不好的,会导致JSON等数据无法正常读取。
PHP闭合标签?>
在PHP中对PHP的分析器是可选的。但是,如果使用闭合标签,任何由开发者,用户,或者FTP应用程序插入闭合标签后面的空格都有可能会引起多余的输出、php错误、之后的输出无法显示、空白页。
因此,如果此文件为纯php文件(没有嵌套HTML),请不要用?>
符号结尾,保持最后一行留空即可。
最好插入一段注释来标明这是文件的底部并定位这个文件在这个应用的相对路径,这样有利于你确定这个文件已经结束而不是被删节的。
不当的: 适当的:
文件必须使用Unix换行符保存,即只有换行(LF或\n
)没有回车(CR或\r
)。这对于那些在Windows下的开发者来说更为重要,但无论如何,确保你的文本编辑器已经设置为使用Unix换行符来保存文件。
在PHP开始标记之前和结束标记之后都不能有空格。输出已经被缓存,所以文件中的空格会导致PHP在输出自己的内容之前就开始了输出,这会使PHP出错且无法输出正确的header()
。
4个空格(space) = 1个制表符(tab)
使用 tab 代替空格有利于那些阅读你的代码的开发者在他们各自所使用的应用程序中自定义缩进方式,使用这种方式保存的文件稍微紧凑一点。
一个文件一个类,class名称与文件名应该相关联,关联的方法是以包所在的目录为根目录,到类所在的文件,将目录分隔符改为下划线即为此类的名称。比如我们的包名称为
Myclass
,我们的类文件所在路径为
Myclass/Foo/Bar.php
,那么这个类的名称就是Myclass_Foo_Bar
。
类名的首字母应该大写。
如果名称由多个词组成,词之间要用下划线分隔,如果class名称与文件名关联,请使用骆驼命名法。
类中所有其他方法的名称应该完全小写并且名称能明确指明这个函数的用途,最好用动词开头。尽量避免过长和冗余的名称。
不当的: class superclass class SuperClass 适当的: class Super_class class Myclass_Foo_Bar // class名和文件名关联
不当的: function fileproperties() // 方法名没有清晰的描述以及下划线分割单词 function fileProperties() // 方法名没有清晰的描述以及使用了驼峰法命名 function getfileproperties() // 还可以!但是忘记了下划线分割单词 function getFileProperties() // 使用了驼峰法命名 function get_the_file_properties_from_the_file() // 方法名太冗长 适当的: function get_file_properties() // 清晰的方法名描述,下划线分割单词,全部使用小写字母
当你的类或文件名是一个常见词语时,或者是很可能与另一个PHP脚本同名时,使用一个唯一的前缀来避免冲突。
你必须始终明白这一点:你的最终用户可能会运行其它第三方的附加组件或者PHP脚本。选择一个能够唯一标识开发者或公司的前缀。
不当的: class Email pi.email.php class Xml ext.xml.php class Import mod.import.php 恰当的: class Pre_email pi.pre_email.php class Pre_xml ext.pre_xml.php class Pre_import mod.pre_import.php
变量名应该只包含小写字母,用下划线分隔,并且能适当地指明变量的用途和内容。那些短的、无意义的变量名应该只作为迭代器用在for()
等循环里。
不当的: $j = 'foo'; // 单字符变量应该只作为for()的循环变量使用 $Str // 使用了大写字母 $bufferedText // 使用了驼峰命名,而且变量名应该更短,并有清晰的语法含义 $groupid // 多个词组,应该使用下划线分割 $name_of_last_city_used // 太长了 适当的: for ($j = 0; $j < 10; $j++) $str $buffer $group_id $last_city
如为私有变量,请在变量名前方加上下划线。
private $_foo
常量命名除了要全部用大写外,其他的规则都和变量相同。为统一标识,可以为常量加上指定前缀。
不当的: define('myConstant', 'foo'); // 未使用下划线分割单词,未全部使用大写字母 define('N', '2'); // 不能使用单个字母作为常量 define('S_C_VER', '1.0'); // 常量名没有清晰的含义 恰当的: define('MY_CONSTANT', 'foo'); define('NEWLINE', '2'); define('SUPER_CLASS_VERSION', '1.0');
通常,代码应该被详细地注释。这不仅仅有助于给缺乏经验的程序员描述代码的流程和意图,而且有助于给你提供丰富的内容以让你在几个月后再看自己的代码时仍能很好的理解。 注释没有强制规定的格式,但是建议添加以下的形式。
文档块(DocBlock) 式的注释要写在类和方法的声明前,这样它们就能被集成开发环境(IDE)捕获:
/** * Super Class * * @package Package Name * @subpackage Subpackage * @category Category * @author Author Name * @link http://example.com */ class Super_class {
/** * Encodes string for use in XML * * @access public * @param string * @return string */ function xml_encode($str)
引用文件和定义常量注释
/** 定义变量 **/ define('MY_CONSTANT', 'foo'); /** 引用文件 **/ require_once 'Foo/Bar.php';
使用行注释时,在大的注释块和代码间留一个空行,行间注释采用双斜线注释法。
// break up the string by newlines $parts = explode("\n", $str); // A longer comment that needs to give greater detail on what is // occurring and why can use multiple single-line comments. Try to // keep the width reasonable, around 70 characters is the easiest to // read. Don't hesitate to link to permanent external resources // that may provide greater detail: // // http://example.com/ $parts = $this->foo($parts);
大括号换行规则与linux内核书写规则一致。if/else
、while
、do/while
、for
、switch
这些可以带语句块的语句,语句块的{
或}
应该和关键字写在同一行,用空格隔开,而不是单独占一行。
if ($foo) { } else if ($bar) { }
函数定义的{
和}
单独占一行,这一点和语句块的规定不同。
class Super_class { function __construct() { } }
switch
和语句块里的case
、default
对齐写,也就是说语句块里的case
、default
标号相对于switch
不往里缩进,但标号下的语句要往里缩进。
switch ($foo) { case 'A': 语句列表 case 'B': 语句列表 default: 语句列表 }
函数中用逗号来分隔参数,所有的参数与前面的逗号之间要空格(第一个参数除外)。
public function connect($host, $port, $db, $user, $password, $charset = NULL)
除了参数之间要使用空格外,所有操作符之间都要使用空格,包括字符连接符.
。
$a = "Hello"; $a = ($b = 4) + 5; $a = $b . ':' . $c
方括号及圆括号内的空格符
通常情况下,不要在方括号[]
和圆括号()
内增加任何空格符。唯一的例外就是为了提高可读性和区别开它们与函数,在接受参数的PHP语法控制结构所使用的括号里,需要增加空格符(declare
、do/while
、elseif
、for
、foreach
、if
、switch
、while
)。
不当的: $arr[ $foo ] = 'foo';
适当的: $arr[$foo] = 'foo'; // 数组键值的方括号内没有空格
不当的: function foo ( $bar ) { }
适当的: function foo($bar) // 函数声明的圆括号内没有空格 { }
不当的: foreach( $query->result() as $row ) // PHP语法控制结构之后有空格,但不是在圆括号内
适当的: foreach ($query->result() as $row)
1、类的内部方法排序为
__construct private protected public __destruct
2、属性的排序为
private protected public
在PHP中,逻辑与和逻辑或有两种表现方式:&&
、||
和and
、or
,他们表示的含义都是相同的,但是他们的优先级不同
运算符优先级的顺序是&&
(||
)、=
、and
(or
)
$a=1 && 0; echo $a; //返回 空 $a=1 and 0; echo $a; //返回 1
部分PHP函数执行失败时返回 FALSE
, 但也可能有一个有效的返回值 ''
或 0
, 它在松散比较中会被计算为FALSE
. 在条件语句中使用这些返回值的时候,为了确保返回值是你所预期的类型而不是一个有着松散类型的值,请进行显式的比较。
在返回和检查你自己的变量时也要遵循这种严格的方法,必要时使用===
和 !==
。
不当的: // 如果 'foo' 位于此字符串的起始处,strpos将返回 0,
// 此处条件判断的结果为TRUE if (strpos($str, 'foo') == FALSE)
恰当的: if (strpos($str, 'foo') === FALSE)
不当的: function build_string($str = '') {
if ($str == '') // uh-oh! 如果传递的参数是FALSE或者整数0那会怎么样? {
}
}
恰当的: function build_string($str = '') {
if ($str === '') {
}
}
1、所有变量均区分大小写,包括普通变量以及$_GET
、$_POST
、$_REQUEST
、$_COOKIE
、$_SESSION
、$GLOBALS
、$_SERVER
、$_FILES
、$_ENV
等
$abc = 'abcd'; echo $abc; //输出 'abcd' echo $aBc; //无输出 echo $ABC; //无输出
2、常量名默认区分大小写,通常都写为大写
define('ABC','Hello World'); echo ABC; //输出 Hello World echo abc; //输出 abc
3、函数名、方法名、类名 不区分大小写,但推荐使用与定义时相同的名字
function show() {
echo "Hello World";
} show(); //输出 Hello World 推荐写法 SHOW(); //输出 Hello World class cls {
static function func(){
echo "hello world";
}
} cls::funC(); //输出hello world Cls::funC(); //输出hello world
4、魔术常量不区分大小写,推荐大写
包括:
__LINE__
、__FILE__
、__DIR__
、__FUNCTION__
、__CLASS__
、__METHOD__
、__NAMESPACE__
。
echo __file__; //输出 /web/filename.php echo __FILE__; //输出 /web/filename.php
5、NULL
、TRUE
、FALSE
不区分大小写,但是关键字应该总是完全大写的。
$a = null; $b = NULL; $c = true; $d = TRUE; $e = false; $f = FALSE; var_dump($a == $b); //输出 bool(true) var_dump($c == $d); //输出 bool(true) var_dump($e == $f); //输出 bool(true)
6、类型强制转换,不区分大小写
包括:
(int)
、(integer)
– 转换成整型
(bool)
、(boolean)
– 转换成布尔型
(float)
、(double)
、(real)
– 转换成浮点型
(string)
– 转换成字符串
(array)
– 转换成数组
(object)
– 转换成对象
$a=1; var_dump($a); //输出 int 1 $b=(STRING)$a; var_dump($b); //输出string '1' (length=1) $c=(string)$a; var_dump($c); //输出string '1' (length=1)
涉及到的比较值为:
0
、''
、null
、false
、true
、FLASE
、TREU
、array()
。
//比较值 '' NULL 0 false true FALSE TRUE //相等判断 '' == NULL == 0 == false (相等) array() = 0 == NULL == false (相等) array() <> '' (不相等) //恒等判断 //任何两个数比较都不恒等 var_dump(false == FALSE); //bool(true) var_dump(false === FALSE); //bool(true) var_dump(true == TRUE); //bool(true) var_dump(true === TRUE); //bool(true) var_dump('' == NULL); //bool(true) var_dump('' === NULL); //bool(false) var_dump('' == 0); //bool(true) var_dump('' === 0); //bool(false) var_dump('' == false); //bool(true) var_dump('' === false); //bool(false) var_dump('' == true); //bool(false) var_dump('' === true); //bool(false) var_dump(null == 0); //bool(true) var_dump(null === 0); //bool(false) var_dump(null == false); //bool(true) var_dump(null === false); //bool(false) var_dump(null == true); //bool(false) var_dump(null === true); //bool(false) var_dump(0 == false); //bool(true) var_dump(0 === false); //bool(false) var_dump(0 == true); //bool(false) var_dump(0 === true); //bool(false) //对true的一些判断 var_dump('1' == true); //bool(true) var_dump('1' === true); //bool(false) var_dump(1 == true); //bool(true) var_dump(1 === true); //bool(false) var_dump(array() == true); //bool(false) var_dump(array() === true); //bool(false) //array()比较 var_dump(array() == ''); //bool(false) var_dump(array() === ''); //bool(false) var_dump(array() == NULL); //bool(true) var_dump(array() === NULL); //bool(false) var_dump(array() == 0); //bool(false) var_dump(array() === 0); //bool(false) var_dump(array() == false); //bool(true) var_dump(array() === false); //bool(false) var_dump(array() == true); //bool(false) var_dump(array() === true); //bool(false) //恒等比较 var_dump(0 === '0'); //bool(false) var_dump(0 === 00); //bool(true) var_dump(00 === intval('0')); //bool(true)
切记不要在一行写多条语句
不当的: $foo = 'this'; $bar = 'that'; $bat = str_replace($foo, $bar, $bag);
适当的: $foo = 'this'; $bar = 'that'; $bat = str_replace($foo, $bar, $bag);
除非你需要解析变量那么请一直使用单引号,如果需要解析变量请使用大括号({ }
),大括号用来明确变量名的界线。如果字符串包含单引号(' '
)的话你可以使用双引号(" "
),这样就不用转义了。
不当的: "My String" // 没有解析变量,不需要使用双引号 "My string $foo" // 解析变量需要使用括号 'SELECT foo FROM bar WHERE baz = \'bag\'' // 需要转义单引号''时这样写比较难看,可以使用双引号 适当的: 'My String' "My string {$foo}" "SELECT foo FROM bar WHERE baz = 'bag'"
MySQL的关键词都是大写:
SELECT
、INSERT
、UPDATE
、WHERE
、AS
、JOIN
、ON
、IN
等。
考虑到易读性,把长的查询分成多行,最好是每行只有一个从句或子从句。
不当的: // 关键词是小写并且一行中的查询太长(...表示行的继续)
$query = $this->db->query("select foo, bar, baz, foofoo, foobar as raboof, foobaz from exp_pre_email_addresses ...where foo != 'oof' and baz != 'zab' order by foobaz limit 5, 100");
适当的: $query = $this->db->query("SELECT foo, bar, baz, foofoo, foobar AS raboof, foobaz FROM exp_pre_email_addresses WHERE foo != 'oof' AND baz != 'zab' ORDER BY foobaz LIMIT 5, 100");
适当的时候,提供函数参数的缺省值,这有助于防止因错误的函数调用引起的PHP错误,另外提供常见的备选值可以节省几行代码 例如:
function foo($bar = '', $baz = FALSE)
以上是Annuo整理的PHP编码规范,你可以阅读 PHP手册之语言参考 以了解更多。
+ 腾讯alloyteam团队编写的前端代码规范:http://alloyteam.github.io/code-guide/
+ JavaScript 规范: https://github.com/adamlu/javascript-style-guide
+ + 更多: https://github.com/justjavac/free-programming-books-zh_CN