本文旨在整理 PHP 使用过程中常见容易忽略而导致错误之处,后续会持续补充更新。
同时,也是更深层次理解 PHP 实现原理、设计出发点,其中一些可发现开发者为了满足灵活扩展而专门进行的设计,善用则佳,乱用则损。
PS:没有最好的语言,只有最合适的工具。
类名、方法名不区分大小写
结论:不区分大小写的有如下场景,类名、函数(方法)名不区分大小写,可能要让别人耻笑了。
- 类名
- 函数、方法名
- 魔术常量:
__LINE__
、__FILE__
、__DIR__
、__FUNCTION__
、__CLASS__
、__METHOD__
、__NAMESPACE__
等 - NULL、TRUE、FALSE
- 类型强制转换中的类型关键词
Note: Function names are case-insensitive, though it is usually good form to call functions as they appear in their declaration.
声明:
- 强烈建议遵从统一大小写规范,避免困扰及其他语言切换理解成本。
- 脚本语言以其灵活、解释执行的特性具有诸多优势,但应充分了解其弊端
参考阅读:PHP大小写敏感问题整理
array_merge()
中出现null
的影响
结论:array_merge()
要求每个参数必须为数组,其中任一参数非数组将导致Warning和结果为NULL
最佳实践:array_merge()
前进行非空判断或强制类型转换
反思:弱类型语言,在处理上切记小心类型差异的影响。在PHP7之后的发展趋势上,PHP在逐步增强类型规范、约束。
代码示例:
1 | $foo = 'foo'; |
array_merge
和+
的区别
二者相同作用:合并一个或多个数组,将一个数组附件到前一个数组之后。
区别:键名相同时,如何处理?(后者覆盖前者、保留前者、后者追加,一共有着3种情形)
array_merge
:键名相同,字符串键名时后者覆盖前者,数字键则追加至尾部。+
:相同键名时,仅保留第一个数组中元素,后者重复键值忽略(不区分键类型是数值or字符串)
1 | // 数字索引的例子 |
1 | // 索引数组,索引键为字符串 |
参考阅读:function.array-merge
索引数组的索引值
- 索引可以非连续,非连续索引的影响:
json_encode()
返回结果数组 or 对象
1 | $foo = ['a', 'b', 'c']; |
- 如何重建数组索引,恢复连续自增索引值
array_values()
array_slice($foo, 0)
- 二者效率是否有差异?原理有和区别?
1 | $foo = ['a', 'b', 'c']; |
json_encode()
返回JSON数组还是对象
如果 PHP 服务向前端或 Java/Golang 等强类型语言服务提供接口时,经常面临吐槽。
返回数据字段有时是数组,有时却是对象,对强类型语言而言就是灾难。
首先,搞清JSON 中数组Array、对象 Object 的各自定义(详见:json.org):
- Array:值的有序集合,以
[
开始,以]
结束 - Object:无序的
名称/值
对的集合,以{
开始,以}
结束
PHP 中常用json_encode ( mixed $value [, int $options = 0 [, int $depth = 512 ]] ) : string
函数进行特定类型的序列化输出。第二个参数options
传递不同JSON 常量
来控制序列化输出结果。
1 | // |
json_encode()
总结:
- 缺省第二参数时
- 空数组时,
json_encode()
后输出数组 Array
- 索引数组(键为数字),且索引键连续,
json_encode()
后输出数组 Array
- 索引数组(键为数字),但索引键非连续,
json_encode()
后输出对象 Object
- 关联数组(键为字符串),
json_encode()
后输出对象 Object
- 空数组时,
- 如需强制结果返回对象
- 将
json_encode($value, JSON_FORCE_OBJECT)
,将结果强制返回对象
- 将
- 如需强制结果返回数组
- 索引数组的结果强制返回数组,重建索引保证索引连续,则
json_encode
后结果为 JSON 数组 - 关联数组,结果仅返回数组则丢失 key 信息,需根据数据结构明确是否合理,如坚持需要可通过
array_values()
仅取值、忽略键信息
- 索引数组的结果强制返回数组,重建索引保证索引连续,则
实例:
1 | // 空数组,返回空数组 |
array($foo)
和(array)$foo
的区别
array()
是数组声明,和[]等价(array)
是强制类型转换
在非空变量上,二者作用相当;应特别注意,当$foo=null
时,二者区别:
1 | $in = null; |
全角、半角字符
在进行字符替换时,常用来将多个空格处理成单个、或过滤空格。
但在全角状态下空格的识别,较为少见,但是比较容易忽略的。
匹配时,容易忽略的「全角空格」
1 | // 预期:替换所有空格 |
有问题的正则遇到全角符号
- 正则中
[]
表示多个可选的字符,但只允许单个字符,全角空格为三字符(\xE3\x80\x80
),则会按三个分别分别匹配、替换 - 这样就会误替换部分中文中的字符为空,导致乱码
- preg中u(PCRE_UTF8)修饰符,可支持utf8编码处理,从而支持多字节匹配问题
- PS:虽然preg中的u修饰符可解决上述case,但应更加准确适用正则及其对应含义。
正则中[]的概念:[abc] A single character of: a, b or c
1 | // 注意,原始字符串中包含「全角空格」,正则中[]内也有此「全角空格」 |
字符编码
详见另一篇文章:PHP中编码检测