这也是为什么上面那段简单的代码会输出 a 到 z, 然后 继续 输出 aa到 yz。 它停在了 za,那是它遇到的第一个比 z 大 的:
php> var_export((boolean)('za' < 'z')) . "\n"; false事实上,在 PHP 里 有合适的 方式在循环中输出 a 到 z 的值:
for ($i = ord('a'); $i <= ord('z'); $i++) { echo chr($i) . "\n"; }或者是这样:
$letters = range('a', 'z'); for ($i = 0; $i < count($letters); $i++) { echo $letters[$i] . "\n"; } 常见 错误 #9: 忽视代码规范尽管忽视代码标准并不直接导致需要去调试 PHP 代码,但这可能是所有需要谈论的事情里最重要的一项。
在一个项目中忽视代码规范能够导致大量的问题。最乐观的预计,前后代码不一致(在此之前每个开发者都在“做自己的事情”)。但最差的结果,PHP 代码不能运行或者很难(有时是不可能的)去顺利通过,这对于 调试代码、提升性能、维护项目来说也是困难重重。并且这意味着降低你们团队的生产力,增加大量的额外(或者至少是本不必要的)精力消耗。
幸运的是对于 PHP 开发者来说,存在 PHP 编码标准建议(PSR),它由下面的五个标准组成:
PSR-0: 自动加载标准
PSR-1: 基础编码标准
PSR-2: 编码风格指导
PSR-3: 日志接口
PSR-4: 自动加载增强版
PSR 起初是由市场上最大的组织平台维护者创造的。 Zend, Drupal, Symfony, Joomla 和 其他 为这些标准做出了贡献,并一直遵守它们。甚至,多年前试图成为一个标准的 PEAR ,现在也加入到 PSR 中来。
某种意义上,你的代码标准是什么几乎是不重要的,只要你遵循一个标准并坚持下去,但一般来讲,跟随 PSR 是一个很不错的主意,除非你的项目上有其他让人难以抗拒的理由。越来越多的团队和项目正在遵从 PSR 。在这一点上,大部分的 PHP 开发者达成了共识,因此使用 PSR 代码标准,有利于使新加入团队的开发者对你的代码标准感到更加的熟悉与舒适。
常见错误 #10: 滥用 empty()一些 PHP 开发者喜欢对几乎所有的事情使用 empty() 做布尔值检验。不过,在一些情况下,这会导致混乱。
首先,让我们回到数组和 ArrayObject 实例(和数组类似)。考虑到他们的相似性,很容易假设它们的行为是相同的。然而,事实证明这是一个危险的假设。举例,在 PHP 5.0 中:
// PHP 5.0 或后续版本: $array = []; var_dump(empty($array)); // 输出 bool(true) $array = new ArrayObject(); var_dump(empty($array)); // 输出 bool(false) // 为什么这两种方法不产生相同的输出呢?更糟糕的是,PHP 5.0之前的结果可能是不同的:
// PHP 5.0 之前: $array = []; var_dump(empty($array)); // 输出 bool(false) $array = new ArrayObject(); var_dump(empty($array)); // 输出 bool(false)这种方法上的不幸是十分普遍的。比如,在 Zend Framework 2 下的 Zend\Db\TableGateway 的 TableGateway::select() 结果中调用 current() 时返回数据的方式,正如文档所表明的那样。开发者很容易就会变成此类数据错误的受害者。
为了避免这些问题的产生,更好的方法是使用 count() 去检验空数组结构:
// 注意这会在 PHP 的所有版本中发挥作用 (5.0 前后都是): $array = []; var_dump(count($array)); // 输出 int(0) $array = new ArrayObject(); var_dump(count($array)); // 输出 int(0)顺便说一句, 由于 PHP 将 0 转换为 false , count() 能够被使用在 if() 条件内部去检验空数组。同样值得注意的是,在 PHP 中, count() 在数组中是常量复杂度 (O(1) 操作) ,这更清晰的表明它是正确的选择。
另一个使用 empty() 产生危险的例子是当它和魔术方法 _get() 一起使用。我们来定义两个类并使其都有一个 test 属性。
首先我们定义包含 test 公共属性的 Regular 类。
class Regular { public $test = 'value'; }然后我们定义 Magic 类,这里使用魔术方法 __get() 来操作去访问它的 test 属性:
class Magic { private $values = ['test' => 'value']; public function __get($key) { if (isset($this->values[$key])) { return $this->values[$key]; } } }好了,现在我们尝试去访问每个类中的 test 属性看看会发生什么:
$regular = new Regular(); var_dump($regular->test); // 输出 string(4) "value" $magic = new Magic(); var_dump($magic->test); // 输出 string(4) "value"到目前为止还好。
但是现在当我们对其中的每一个都调用 empty() ,让我们看看会发生什么:
var_dump(empty($regular->test)); // 输出 bool(false) var_dump(empty($magic->test)); // 输出 bool(true)咳。所以如果我们依赖 empty() ,我们很可能误认为 $magic 的属性 test 是空的,而实际上它被设置为 'value'。