字符串
- 双引号或者heredoc其中的变量 以及
\
开始的符合8进制16进制和特殊符号 - 字符串底层是C语言的结构体,所以可以用
[]
或{}
来访问某个字符 - 字符串最大长度可以达到2G内存
- C语言字符串
\0
代表字符串结束,但PHP结构体是有个长度字段,可以让二进制字符串安全 - 用超出字符串长度的下标写入将会拉长字符串并以空格填充
- UTF-8 编码
16进制 Unicode 编码范围 0800 - FFFF
2进制 1110xxxx 10xxxxxx 10xxxxxx
为了通用优先选择UTF-8 3个字节,为了节省空间用GBK 2个字节
数组
- key 可以是integer 或者 string (包含合法整形的字符串,浮点数和布尔值都会被转化为整形)
- unset() 后,不会重建索引
遍历中的引用分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$arr = [1,2,3];
foreach ($arr as $key => &$value) {
}
echo $value; // 3 是 &$arr[2] = 3;
foreach ($arr as $key => $value) {
}
var_dump($arr); // [1,2,2]
// 循环1 $value = &$arr[2] = $arr[0] = 1;
// 循环2 $value = &$arr[2] = $arr[1] = 2;
// 循环3 $value = &$arr[2] = $arr[2] = 2;位运算:
$a&1 == 0 偶数 反之奇数
正则表达式
定义
组成 = 元字符 + 普通字符
常见元字符1
2
3
4
5
6
7
8
9
10
11
12
13
14
15^ 匹配字符串的开始
$ 匹配字符串的结束
. 匹配除换行以外的任意字符
\w 匹配字母或者数字或者下划线
\W 不匹配字母数字下划线
\s 匹配任意的空字符 相当于[\f\r\n\t\v]
\d 匹配任意的数字
\b 匹配单词的开始或者结束
\xxx 查找以八进制xxx规定的字符
\xdd 查找以十六进制dd对顶的字符
\uxxx 查找以十六进制 xxxx 规定的 Unicode 字符
[abcd] 匹配任意一个字符
[a-d] 匹配任意一个字符
[^abcd] 不匹配任意一个字符
[\u4e00-\u9fa5] 匹配任意单个汉字
常见限定符 (限定的是前面一个单元)1
2
3
4
5
6
7| 或关系
* 匹配0到多个,相当于{0,}
? 匹配0到1个,相当于{0,1}
+ 匹配至少1个字符,相当于{1,}
{n} 匹配n个字符
{n,} 匹配至少n个字符
{n,m} 匹配n到m个字符
环视1
2
3
4(?=exp) 位置后面能匹配exp
(?!=exp) 位置后面不能匹配exp
(?<=exp) 位置前面能匹配exp
(?<!exp) 位置前面不能匹配exp
贪婪与懒惰
通常的行为是尽可能匹配多的字符(回溯)
只要在它后面加一个问号,匹配成功的前提是使用最少的重复
1 | <?php |
回溯
贪婪模式的回溯是影响性能
习惯
- 优先使用单引号
内置函数:
1
21. 邮件过滤:$email = filter_var('hi@uiste.com', FILTER_VALIDATE_EMAIL);
2. 获取文件扩展名:pathinfo($filename, PATHINFO_EXTENSION);strtr 与 str_replace 函数前者优先级更高
yield 实现协程 生成器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57function createRange($number){
for($i=0;$i<$number;$i++){
yield time();
}
}
$result = createRange(10); // 这里调用上面我们创建的函数
foreach($result as $value){
sleep(1);
echo $value , PHP_EOL;
}
1554027375
1554027376
1554027377
1554027378
1554027379
1554027380
1554027381
1554027382
1554027383
1554027384
[Finished in 10.2s]
我们来还原一下代码执行过程。
首先调用 createRange 函数,传入参数10,但是 for 值执行了一次然后停止了,并且告诉 foreach 第一次循环可以用的值。
foreach 开始对 $result 循环,进来首先 sleep(1) ,然后开始使用 for 给的一个值执行输出。
foreach 准备第二次循环,开始第二次循环之前,它向 for 循环又请求了一次。
for 循环于是又执行了一次,将生成的时间戳告诉 foreach .
foreach 拿到第二个值,并且输出。由于 foreach 中 sleep(1) ,所以, for 循环延迟了1秒生成当前时间
所以,整个代码执行中,始终只有一个记录值参与循环,内存中也只有一条信息。
无论开始传入的 $number 有多大,由于并不会立即生成所有结果集,所以内存始终是一条循环的值。
读取超大文件
PHP开发很多时候都要读取大文件,比如csv文件、text文件,或者一些日志文件。这些文件如果很大,比如5个G。这时,直接一次性把所有的内容读取到内存中计算不太现实。
<?php
header("content-type:text/html;charset=utf-8");
function readTxt()
{
# code...
$handle = fopen("./test.txt", 'rb');
while (feof($handle)===false) {
# code...
yield fgets($handle);
}
fclose($handle);
}
foreach (readTxt() as $key => $value) {
# code...
echo $value , PHP_EOL;
}语法支持带来更高效率 用 ** 更快
1
2echo 2**3 , PHP_EOL;
echo pow(2,3) , PHP_EOL;用 … 定义变成参数
- <=> 大于为1,等于为0,小于为-1
- if 使用技巧给定初始值,比增加else效率更高
- if 使用技巧 三元运算符替换
- 去掉多此一举的写法 直接return 出去,尽量精简代码
- 根据二维数组中的某个键值排序:
1
2// 根据uv_price排序
array_multisort(array_column($productData, 'uv_price'), SORT_DESC, $productData);
php坑人题
1 |
|
1 |
|
1 |
|
1 |
|