SPL
参考:https://www.imooc.com/video/2510/0
什么是 SPL
Standard PHP Library 的缩写,它是用于解决典型(常见)问题的一组接口与类的集合。
典型(常见)问题
数学建模/数据结构
解决数据怎么存储的问题
元素遍历
数据怎么查看的问题
常用方法的同意调用
通用方法(数组、集合的大小)
自定义遍历
类定义的自动装载
让 php 程序适应大型项目的管理要求,把功能的实现分散到不同文件中。
参考:https://www.imooc.com/video/2510/0
Standard PHP Library 的缩写,它是用于解决典型(常见)问题的一组接口与类的集合。
解决数据怎么存储的问题
数据怎么查看的问题
通用方法(数组、集合的大小)
自定义遍历
让 php 程序适应大型项目的管理要求,把功能的实现分散到不同文件中。
按值排序,值与下标没有绑定,升/降。
按元素值进行排序,值与下标绑定。
按键的值进行排序。
自然排序
1 | $array1 = $array2 = array("img12.png", "img10.png", "img2.png", "img1.png"); |
以上例程会输出:
1 | Standard sorting |
自然排序, 不区分大小写. natsort 是区分大小的.
返回当前被内部指针指向的数组单元的值,并不移动指针。如果内部指针指向超出了单元列表的末端,current() 返回 FALSE。 pos()就是 current()的别名.
返回数组中当前的 键/值 对, 并将数组指针向前移动一步.
将数组的内部指针指向最后一个单元.
返回数组中内部指针指向的当前单元的键名。
将数组内部的指针向前移动一位.
将数组内部的指针倒回一位. 和 next 刚好相反
将数组的内部指针指向第一个单元.
将一个或多个单元压入数组的末尾 (入栈)
弹出数组最后一个单元 (出栈)
将数组开头的单元移出数组.
在数组开头插入一个或多个单元.
将数组中的所有键名修改为全大写或者全小写
将一个数组分割分成多个
返回数组中指定的一列
创建一个数组, 用一个数组的值作为键名, 另一个数组的值作为值.
统计数组中的每个值出现的次数
计算数组的差集, 比较$arr, $brr, $crr, $drr…多个数组, 返回$arr 中有而其他数组中没有的 键 对应的值
计算数组的差集, 和 array_diff_assoc 的区别在于不检查键.
array array_fill_keys ( array $keys , [mixed] $value )
使用 value
参数的值作为值,使用 keys
数组的值作为键来填充一个数组。
给定的值填充数组
用回调函数过滤数组中的单元
示例:
1 | function odd($var) |
ps: & 位与运算, 当都是 1 时则为 1, 否则为 0
交换数组中的键和值.
计算数组的交集, 比较$arr, $brr, $crr, $drr…多个数组, 返回$arr 中有而其他数组中也有的 键 对应的值
计算数组的交集. 比较$arr, $brr, $crr, $drr…多个数组, 返回$arr 中有而其他数组中也有的值
检查数组中是否有指定的键
array_key_exists
的别名.
返回数组中部分的或所有的键
为一个或多个数组的每个元素应用回调函数.
递归的合并多个数组, 相同键的值会合并到一个数组中.
合并多个数组, 相同键的值会覆盖.
可以用来一次对多个数组进行排序,或者根据某一维或多维对多维数组进行排序。
返回 array 的一个拷贝,并用 value 将其填补到 size 指定的长度。如果 size 为正,则填补到数组的右侧,如果为负则从左侧开始填补。如果 size 的绝对值小于或等于 array 数组的长度则没有任何填补。有可能一次最多填补 1048576 个单元。
计算数组中所有值得乘积
从数组中随机取出一个或多个单元
将回调函数 callback
迭代地作用到 array
数组中的每一个单元中,从而将数组简化为单一的值。
使用后面数组元素的值替换数组 array1
的值。 如果一个键存在于第一个数组同时也存在于第二个数组,它的值将被第二个数组中的值替换。 如果一个键存在于第二个数组,但是不存在于第一个数组,则会在第一个数组中创建这个元素。 如果一个键仅存在于第一个数组,它将保持不变。 如果传递了多个替换数组,它们将被按顺序依次处理,后面的数组将覆盖之前的值。 是递归的:它将遍历数组并将相同的处理应用到数组的内部值。
与 array_replace_recursive 的区别就是他是非递归的.
返回单元顺序相反的数组
在数组中搜索给定的值,如果成功则返回首个相应的键名,如果失败则返回 false。
在数组中搜索给定的值,如果成功则返回 true,如果失败则返回 false。
从数组中取出一段.
1 | $foo = [1,2,3,4,5,6,7,8,9]; |
去掉数组中的某一部分, 并用其他值代替.
对数组中所有值求和
移除数组中重复的值, 返回过滤后的数组.
返回数组的值并建立数字索引.
对数组中的每个成员递归地应用自定义函数, 函数默认传入两个参数, 值 和 键.
同 array_walk_recursive, 但是不递归.
新建一个数组.
新建一个数组, 包括变量名和他们的值.
它的作用和 compact
刚好相反.
计算数组中的单元数目, 或对象中的属性个数. sizeof 是 count 的别名.
把数组中的值赋给一组变量. 注意: PHP5 中, list()
从最右边的参数开始赋值; PHP7 中, list()
从最左边的参数开始赋值. 通常而言, 不建议依赖于操作的顺序, 在未来可能会再次发生改变.
创建一个包含指定范围单元的数组.
打乱数组
示例:
1 | public function onRequest(?string $action): ?bool |
已上示例表示传入的参数$action 可以是 null 或者字符串,不能是其他类型。同理:返回值只能是 bool 或者 null。
zend_types.h 中定义了所有变量的数据类型。
zend_hash.h 中定义了数组相关的 api。
zend_alloc_sizes.h 和 zend_alloc.c 和 zend_alloc.h 这三个文件是和内存相关。
zend_alloc_sizes.h 中重点掌握 ZEND_MM_BINS_INFO 这个宏定义。
zend_alloc.h 中重点掌握以下函数:
1 | ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_ATTRIBUTE_MALLOC; |
zend_alloc.c 中重点掌握 AG 这个宏:
1 | typedef struct _zend_alloc_globals { |
ReflectionClass
ReflectionMethod
ReflectionClass 类报告了一个类的有关信息。
ReflectionMethod 类报告了一个方法的有关信息。
实例化 ReflectionMethod 的时候需要传入对象和方法两个参数。
通常 ReflectionMethod 可以作为参数传递到ReflectionClass的getMethod。来限制获取的方法类别。
1 | let arr = [2, 22, 2, 2]; |
1 | $input = ["a" => "green", "red", "b" => "green", "blue", "red"]; |
补充 : 如何重建数组的索引 ?
1 | //使用array_values 返回数组的值并建立数字索引. |
filter_var — 使用特定的过滤器过滤一个变量
进程数和线程数设置要考虑以下条件
比较一下三种方式, 哪种更好?
个人感觉, 在 swoole 中, 因为是全协程异步. 所以适合单进程多线程, 然后线程数目设置等于 CPU 核数.
下载 php 的 tar.gz 包,解压后进入 Zend 目录,其中有 bench.php 和 micro_bench.php 两个文件。
使用不同版本的 php 分别执行这两个文件,看看执行时间差距。
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。
1 | #include <stdio.h> |
结果:
1 | var1 变量的地址: 0x7fff5cc109d4 |
1 | #include <stdio.h> |
结果:
1 | Address of var variable: bffd8b3c |
1 | #include <stdio.h> |
1 | #include <stdio.h> |
int _ p = arr; p++; 这种写法等价与 int _ p = arr + 1
C 语言规定数组代表数组所在内存位置的首地址,也就是 str[0]的地址,即 str=&str[0];
而 printf(“%s\n”, str); 为什么用首地址就可以输出字符串。
因为还有一个关键,在 C 语言中字符串常量的本质其实是一个地址,这个是许多初学者比较难理解的问题。
新建一个 c 文件,hello.c
1 | #include <stdio.h> |
然后
1 | gcc ./hello.c |
在当前目录下生成 a.out 可执行文件。
1 | ./a.out |
输出 hello word 。
这个编译过程经过了四个步骤:
1 | gcc -o hello.i hello.c -E |
1 | #define R 20 |
define 中是没有 c 语法的,只是单纯的字符串替换
宏非常简单,就是“替换”
typedef 和预处理没什么关系, 但是和宏比较容易混淆.
它的作用是给变量类型起别名
1 | #if 整型常量表达式 1 |
它的意思是:如常“表达式 1”的值为真(非 0),就对“程序段 1”进行编译,否则就计算“表达式 2”,结果为
真的话就对“程序段 2”进行编译,为假的话就继续往下匹配,直到遇到值为真的表达式,或者遇到 #else。这一
点和 if else 非常类似。
需要注意的是,#if 命令要求判断条件为“整型常量表达式”,也就是说,表达式中不能包含变量,而且结果必须
是整数;而 if 后面的表达式没有限制,只要符合语法就行。这是 #if 和 if 的一个重要区别。
1 | #ifdef 宏名 |
它的意思是,如果当前的宏已被定义过,则对“程序段 1”进行编译,否则对“程序段 2”进行编译。
1 | #ifndef 宏名 |
与 #ifdef 相比,仅仅是将 #ifdef 改为了 #ifndef。它的意思是,如果当前的宏未被定义,则对“程序段 1”进行编
译,否则对“程序段 2”进行编译,这与 #ifdef 的功能正好相反。
最后需要注意的是,#if 后面跟的是“整型常量表达式”,而 #ifdef 和 #ifndef 后面跟的只能是一个宏名,不能是
其他的。
结构体是不同类型的变量的集合, 与数组相反, 数组是相同类型变量的集合
示例: 定义一个名为 house 的结构体,有三种方式:
定义结构体和定义变量分开
1 | #include <stdio.h> |
定义结构体同时定义变量
1 | #include <stdio.h> |
只为一个变量定义结构体
1 | #include <stdio.h> |
1 | #include <stdio.h> |
对齐规则