当你编写更复杂的脚本时,你会发现必须清楚地向自己和他人说明你在做什么以及为什么这么做。注释和“良好的”命名能够帮助你编写清晰易懂的脚本,原因如下:

  1. 当你编写一个耗时超过一周的脚本时,到你完成时,你很可能已经忘记了开始时做了什么,而你很可能会需要知道这些。
  2. 任何常用的脚本最终都需要重写。重写时,记录你当初做了什么会让重写变得更加容易(在许多情况下,甚至是可能的)。
  3. 如果你想向别人展示你的脚本,它们应该是整洁的。

注释


注释是 PHP 解析器会跳过的代码片段。当解析器遇到注释时,它会直接跳过注释部分,继续处理代码的其他部分。PHP 提供了一行注释和多行注释两种类型。

一行注释

一行注释是指从注释开始的位置到该行的末尾,注释的内容仅限于该行。PHP 中可以使用 //# 来表示一行注释(# 的使用不太常见)。这种注释通常用于解释接下来几行代码的作用。例如:

// 打印变量 $message
echo $message;

需要注意的是,一行注释并不一定需要覆盖整行,它只需从注释符号开始的位置开始。例如,以下代码中,$message = ""; 会被执行,但注释部分 //This sets the variable $message to an empty string 不会执行:

$message = ""; //This sets the variable $message to an empty string
一行注释的问题

一行注释通过以下方式结束:

  • 一个换行符(实际的换行符,而不是 \n 换行符标记),或者
  • PHP 关闭标签 ?>

如果一行注释由 PHP 关闭标签结尾,它不会被注释掉,以下代码会输出 "2":

// echo "1"; ?> echo "2";

多行注释

多行注释可以跨越多行,适用于描述函数或类的作用,或者包含那些一行无法容纳的长注释。多行注释的开始使用 /*,结束使用 */。例如:

/* 这是一个
多行注释
它将在我告诉它的时候结束
*/

你还可以使用多行注释来跳过某行的一部分。例如:

$message = "" /*这部分不会被执行*/;

不过,不推荐使用这种方式,因为在某些编辑器中可能会导致混淆。

多行注释的问题

如果多行注释没有正确结束,就会导致错误,除非它是从已存在的多行注释块内开始的(即它是非贪婪的,只对已完成的打开和关闭集进行操作)。以下代码会导致错误:

/* test */ */

而以下代码不会报错:

/* test /* */

因此,多行注释不能嵌套(第一个注释块会被注释掉,但第二个注释块没有开始注释符)。以下代码会导致错误:

/*
开始第一个注释块
/*
开始嵌套注释块
结束嵌套注释块
*/
结束第一个注释块
*/

通过结合不同注释风格,可以快速切换多个注释块(尽管在某些文本编辑器中,显示可能不完全正确)。

示例 1:注释块的切换

原始代码(未注释任何内容,输出为 "block one block two"):

<?php
//*
print "block ";
print "one ";
// */
print "block ";
print "two";
?>

去掉第一行的斜杠后,第一个代码块被注释掉,只会输出 "block two":

<?php
/*
print "block ";
print "one ";
// */
print "block ";
print "two";
?>

由于单行注释 // 会覆盖多行注释 /*...*/,因此可以同时切换两个代码块的注释状态。

示例 2:注释块的切换

原始代码(只输出 "block one"):

<?php
//*
print "block";
print "one";
/*/
print "block";
print "two";
// */
?>

去掉第一行的斜杠后,第一个代码块被注释掉,第二个代码块未被注释,输出 "block two":

<?php
/*
print "block";
print "one";
/*/
print "block";
print "two";
// */
?>

PHPDoc注释

PHPDocumentor 使用多行注释(开头紧跟着一个额外的星号 /**)以及注释块中的其他标准标签来自动生成文档。例如:

/**
 * 这是我的新花哨代码...
 * @author Dr. Who
 * @version 1.0
 */

单行或多行注释的常见问题

当使用常规表达式中的多行注释时,可能会遇到冲突,因为在正则表达式结束时的星号(*)以及关闭标记(/)可能会被解析为注释的结束符,导致后续的 */ 没有正确的开始符号。示例如下:

/*
$subject = "Hi Joe";
$matching = preg_match($subject, '/^Hi.*/');
*/

为避免此问题,可以:

  • 使用其他不太常见的正则表达式分隔符(例如,在大多数情况下,@ 分隔符比 / 更少见)。
  • 使用不可能为真的条件语句来避免正则表达式冲突:
<?php

if (0) {
  $subject = "Hi Joe";
  $matching = preg_match($subject, '/^Hi.*/');
}

?>

通过这种方式,还能避免嵌套问题:

<?php

if (0) {

  if (0) {
    print "Hi ";
  }

  print "Bob";
}

?>

然而,这种方法的一个缺点是文本编辑器可能不会识别这些条件语句,因此可能无法正确进行代码着色(尽管对于调试来说,这是一个优势,因为它能更清楚地显示出被注释掉的块内容)。

编码风格

PHP 编码风格在 PHP 标准推荐中有所定义。

命名

正确命名变量、函数和类对于理解程序非常重要。按照惯例,命名应该采用驼峰命名法(camelCase),并避免使用缩写。

例如,定义以下变量:

$var1 = "PHP";
$var2 = 15;

这些命名对于任何人来说都没有多大意义。但如果你这样命名:

$programmingLanguage = "PHP";
$menuItems = 15;

就会更加清晰。然而,也不要过度命名。例如,$programmingLanguage 这样的名称不太合适,因为它太长,既浪费时间输入,也可能影响可读性。一个更好的名字可能是 $progLanguage,因为它更短,但仍然能让人理解。好的命名应该避免使用注释来标记每个变量的功能。

例如,以下的注释是冗余的,应该去掉:

// 用于编写此脚本的编程语言
$progLanguage = "PHP";

// 个人菜单中允许的最大项目数
$maxMenuItems = 15;

魔法数字

在程序中使用数字时,重要的是这些数字要有明确的意义。例如,最好在使用 15 时定义一个变量 $menu_items,而不是重复使用数字 15 却没有解释其含义。唯一的例外是数字 1;通常,程序员需要对某个数字加或减 1,以避免 "off-by-one" 错误,因此 1 可以直接使用而不需要定义。

当你在使用数字之前就定义它们时,后期调整值也会更容易。例如,如果我们有 15 个菜单项,并且在代码中引用了 10 次,那么当我们添加第 16 个菜单项时,只需要修改变量定义,就能在 10 个地方更新代码。

空格

PHP 会忽略多余的空格和空行。这意味着,即使你可以写出以下代码:

if ($var == 1) {echo "Good";} else {echo "Bad";}

更好的写法是使用 PSR-2 格式:

if ($var == 1) {
  echo "Good";
} else {
  echo "Bad";
}

一些程序员喜欢这样写:

if ($var == 1)
{
  echo "Good";
}
else
{
  echo "Bad";
}

你还应该在脚本的不同部分之间使用空行。例如,避免如下代码:

$var = 1;
echo "Welcome!<br />";
echo "How are you today?<br />";
echo "The answer: ";

if ($var == 1) {
  echo "Good";
} else {
  echo "Bad";
}

更好的写法是:

$var = 1;

echo "Welcome!<br />";
echo "How are you today?<br />";

echo "The answer: ";

if ($var == 1) {
  echo "Good";
} else {
  echo "Bad";
}

这样,读者会理解脚本首先声明一个变量,然后向用户问好,最后检查该变量。

指令

通过使用 declare() 命令,可以定义某些 PHP 编译行为。例如:

declare(encoding = "UTF-8");

这样可以设定脚本的字符编码为 UTF-8。

参考资料

Last modified: Thursday, 9 January 2025, 9:53 PM