变量类型说PHP入门门槛低,其中一个原因是我们不需要关心变量的类型,PHP为我们做了自动的转化。但事实上是这样吗?下面就是一个隐蔽的bug。
很神奇吧,php在这里自动将字符串作为整数0来比较了。由此引发了一系列问题:
所以当一个表达式中同时包含0和字符串的时候就要特别留意了,以免被奇葩的bug坑了。 比较符号等号 |
1 2 3 4 5 6 7 8 |
|
>
小于<
被搞糊涂的话,下面还有:
1 2 3 4 |
|
使用==
时,参照javascript中的做法,我们可以使用===
让比较更规范一些,但是>
,<
这些怎么办?只能尽量避免。
很多语言都提供了三元运算符?:
,因为它足够简洁,也够geek。但是php中的表现与其他语言中又不同:
1 2 3 4 5 6 7 8 9 10 |
|
猜猜结果是什么?’horse’,而我们预料中的(在其他语言中)应该是’train’。这种做法被称为”left associative”(左结合),也即上面的表达式在php看来等同于$vehicle = (condition) ? 'horse' : 'feet'
,所以你永远不可能得到中间的结果,这有违人的第一感觉,也与其他语言正好相反。
empty是我在php中非常喜欢的一个方法,这里我说错了,其实它是一个语言结构,而不是一个方法,但是它的使用方式又像一个方法。于是,empty()中包含运算式的话是会报错的,这也造成了它的局限性。
php中的数组应该是一个’数组’,’hash表’,’集合’的结合体,这在使用上有它的方便之处,但是也造成了一些不易理解的地方,尤其体现在一些array相关的方法上。
1 2 3 4 |
|
好吧,其实php中的array就是一个hash表,无论什么情况下。array('bar', 'foo')
就是array('0'=>'bar', '1'=>'foo')
,这样对理解array的一些奇怪表现应该会有帮助,但是下面的方法,有推翻了上面的论述,我将它算做一个bug:
1 2 3 4 5 6 |
|
看到了吧,如果array是个hash表的话,$first和$second显然是不一样的。但是diff的结果却认为这是两个一样的数组。所以在愉快的使用array时,别忘了停下来,测试一下这些隐含的bug。
++
与--
1 2 3 4 5 6 |
|
解决这种++
和--
中的不一致的办法就是根本不用它们,用+=
和-=
代替。
下面这些就与bug无关了,而是php中过于随意的命名规则和变量顺序,像htmlentities
和html_entity_decode
,你能想象这两个方法是一张纸的两面吗?
其实方法的命名不规范问题也不大,但是变量顺序混乱就要人命了,比如array中的一大堆方法,看起来都以array打头,相当清晰。但是你能料到array_filter($input, $callback)
和array_map($callback, $input)
两个方法的回调方法位置正好相反吗?我就经常记错strpos
中哪个参数才是该被搜索的字符串。
还有一个要命的地方就是很多参数的引用传递不明,比如上面的array_filter
是对源对象的一个拷贝,但是array_walk
却是一个引用。这些在上有“粗略”的说明,我想谁也不希望一边翻文档一边写代码吧。
关于php的错误控制其实是一个关于“配置优于约定”还是“约定优于配置”的讨论,而显然php选择了前者。在php中,有一个全局的配置文件“php.ini”,里面关于错误控制的两个选项error_reporting
和display_errors
分别代表错误等级和是否显示错误。
这没有问题,问题是这些配置在运行时是可以修改的。有些框架或有些人为了掩盖无处不在的notice
,将error_reporting
等级调高,或者索性将display_errors
设置为off
,这会让其他开发者困惑,让错误无迹可寻。
这也不是什么问题,最大的问题是php中还有set_error_handler
和set_exception_handler
,看字面意思,这两个都是用来控制错误的。但是在php中,error
和exception
却是不一样的。于是你要么在框架里写上两套一样的handler
方法,要么就索性都不写,由php去决定这些错误该以什么形式表现。最糟糕的是只写一个或者写两套不一样的handler
,这回让人困惑为什么有些错误以一种形式表现,而一些错误又以别的方式出现,而且要找到这些handler
也不是一件容易的事,他们可能出现在任何一个文件的任何一个角落,除非你用debug_backtrace
将堆栈信息都打印出来。
以上大部分内容和例子来自PHP: a fractal of bad design,一个狂热的python教徒。我不是python教徒,甚至连爱好者都说不上,所以写这篇文章只是为了记录php中存在的bug,以防一不小心被坑了。只有有了这些意识,才能在这门语言中更好的发挥,物尽其用。
|