[TOC]
PHP常用系统函数帅哥特供版
- 常用操作
定界符
<<
数组
数组:
prev(); 将内部指针指向数组中的上一个元素,并输出
next(); 数组内部指针移动到下一个值.,并输出
end(); 数组内部指针移动到最后一个值, 即获取数组的最后一个值.,并输出
reset(); 数组内部指针移动到第一个值, 即获取数组的第一个值.,并输出
current(); 返回数组中的当前单元,返回数组中的当前元素的值
array_walk(); 对数组中的每个元素应用定义的函数,使用用户自定义函数对数组中的每个元素做回调处理,操作会影响对原数组
array_map(); 为数组的每个元素应用回调函数,将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组
array_filter(); 用回调函数过滤数组中的单元
array_column(); 从多维数组中返回指定单列的值。
array_multisort(); 多维数组排序,可以按照数组中的一个值进行有优先级的多重排序(这个排序非常厉害,可以对多维数组按照多个个Key进行有优先级的排序)
array_rand(); 从数组中随机取出一个或多个单元的键
range(); 根据范围创建数组,包含指定的元素
shuffle(); 随机打乱数组
array_replace(); 函数使用后面数组的值替换第一个数组的值(相同键替换,不同键保留).
key(); 从关联数组中获取下标,返回数组当前指针的下标(若没有操作过指针,即第一个下标)
array_reverse(); 以相反的顺序返回数组
array_merge(); 如果两个数组存在相同的字符串key后面的一个会覆盖前面的(关联数组的key相同,后面的一个会覆盖前面一个,索引数组下标相同不会覆盖)
使用+合并两个数组; "+"操作符,如果两个数组存在相同的key,前面的一个会覆盖后面的,不管索引还是关联
array_diff_key() 函数用于比较两个(或更多个)数组的键名 ,并返回差集
array_diff(); 数组的值的差集
array_intersect(); 数组的交集
array_intersect_assoc(); 关联数组的交集
implode(); 将一个数组按照规则组成字符串 与explode()相反;
join(); 同implode();
list(); 把数组中的值按Key的顺序赋给一些变量
count(); 计算数组中的单元个数/或者对象中属性个数;
sizeof(); count();的别名
array_keys(); 返回数组中所有的键
array_values(); 返回数组中所有的值;
array_pad(); 使用指定的值将数组填充至指定长度;
array_slice(); 从数组的指定位置, 取出指定长的的数据
array_splice(); 把数组中的一部分去掉并用其他值代替
array_flip(); 翻转键和值(若有重复, 后面覆盖前面)
in_array(); 搜索是否存在指定的值
array_search(); 搜索是否存在指定的值,并返回它的键名
array_key_exists(); 查找数组下标是否存在
array_sum(); 计算数组中所有值的和
array_unique(); 移除数组中重复的值
array_rand(); 从数组中随机一个或多个元素
array_combine(); 创建一个数组,用一个数组作为键,一个作为值
array_fill(); 用指定的值来填充数组
array_map(); 将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。
extract(); 将数组(最好是关联数组,因为索引数组的下标是数字)中的值导入到符号表中
(可指定规则如:若重复则覆盖,或者跳过,或者若重复添加前缀等众多规则),
在使用该函数处理一个数组后(无需重新赋值), 可使用该数组中对应该值的下标作为变量名取到该值,
同时该数组依然被保留使用该数组的变量依然没问题(他的直接返回值是变量的个数);
例如:$arr = ['a'=>'abs'];extract($arr);echo "\$a=". $a; var_dump($arr);
# 入栈,出栈
array_push(); 在数组的尾部追加新值
array_pop(); 在数组的尾部,弹出最后一个元素
array_unshift(); 在数组的开头插入一个或多个元素
array_shift(); 在数组的开头删除数组的第一个值,然后索引会从小打到重新排列,从 0 开始,并以 1 递增
# 排序函数
sort() 用于对数组单元从低到高进行排序。对排序的数组中的单元赋予新的键名这将删除原有的键名不仅是重新排序。
rsort() 函数用于对数组单元从高到低进行排序。请参考 sort() 函数使用。
asort() 函数用于对数组单元从低到高进行排序并保持索引关系。
arsort() 函数用于对数组单元从高到低进行排序并保持索引关系。
ksort() 函数用于对数组单元按照键名从低到高进行排序。本函数会保留原来的键名,因此常用于关联数组。
krsort() 函数用于对数组单元按照键名从高到低进行排序。
usort() 函数使用指定的自定义回调函数,对数组进行排序
uasort(); 使用自定义回调函数, 对数组进行排序,并保持索引
uksort(); 使用用户的自定义函数对数组的下标进行排序.
字符串
字符串:
settype(); 设置变量类型
number_format 以千位分隔符方式格式化一个数字
addslashes(); 函数返回在预定义字符之前添加反斜杠的字符串
str_split(); 将字符串转换为数组(不支持中文);
uuid_create(); 创建一个UUID(需要UUID扩展):
strlen(); 返回字符串长度
strrev(); 反转字符串
ctype_alnum(); 检测是否只包含[A-Za-z0-9]
ctype_alpha(); 检测是否只包含[A-Za-z]注释(ctype_XXX之类的检测函数有很多, 聚币见手册)
gettype(); 获取变量的数据类型
strip_tags(); 清除HTML和PHP标记
htmlspecialchars(); 把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体:展示在浏览器上
htmlspecialchars_decode(); 把一些预定义的 HTML 实体转换为字符
parse_str(); 把查询字符串以数组形式,解析到指定的变量中;
parse_url(); 把查询字符串解析到变量中(按照URL类型);
ltrim(); 移除字符串左侧的空白字符或其他字符。
rtrim(); 移除字符串右侧的空白字符或其他字符。
trim(); 移除字符串两侧指定的字符.当没有指定字符时,清除空白.
str_pad(); 使用另一个字符串将该字符串填充到指定的长度
explode(); 把字符串按照规则组成数组 与implode()相反;
sprintf(); 把%替换为指定内容
strlen(); 返回字符的长度
ucwords(); 转换每个单词的首字母大写
strtoupper(); 将整个字符串转换为大写
strtolower(); 将整个字符串转换为小写
long2ip(); 将IPV4互联网字符串协议转换为IP地址
ip2long(); 将IP地址转换为IPV4格式的互联网协议
substr(); 剪切字符串同时返回剪切部分
isset(); 判断是否存在
empty(); 判断是否为空等于!isset($var) || $var ==false; (PHP7中支持任意表达式,)
is_numeric(); 判断是否是数字
is_int(); 判断是否是整型
is_string(); 判断是否是字符串
is_array(); 判断是否是数组
is_float(); 判断是否是浮点型
is_scalar(); 判断是否是一个标量
strtr(); 转换指定字符
str_replace(); 子字符串替换,返回替换后的数组或字符串
str_ireplace(); 子字符串替换(不区分大小写),返回替换后的数组或字符串
strlen(); 获取字符串的长度
mb_strlen(); 获取字符串的长度(指定编码类型)
printf(); 输出格式化的字符串
strcasecmp(); 二进制安全比较字符串(不区分大小写)(也可以用来比较整型)
strcmp(); 比较两个字符串0:相等. >0:string1小于string2. <0:string1大于sting2
# ASCII操作
chr(); 将ASCII码转换为字符串
ord(); 将字符串转换为ASCII码
# 查找字符串
strrchr(); 查找字符串在另一个字符串最后一次出现的位置.(返回从该字符,到最后的所有);
strstr(); 查找字符串在另一字符串中第一次出现的位置(对大小写敏感)返回剩余部分.
stristr(); 查找字符串在另一字符串中第一次出现的位置(大小写不敏感)返回剩余部分.
strpos(); 返回字符串在另一字符串中第一次出现的位置(对大小写敏感)返回位置
stripos(); 返回字符串在另一字符串中第一次出现的位置(对大小写不敏感)返回位置
strrpos(); 查找字符串在另一字符串中最后一次出现的位置(对大小写敏感)返回位置
strripos(); 查找字符串在另一字符串中最后一次出现的位置(对大小写不敏感)返回位置
strpbrk(); 在字符串中查找一组字符的任何一个字符。
# 编码相关
mb_detect_encoding 检测字符串 str 的编码。
iconv(); 转换字符串编码类型
mb_convert_encoding 转换编码类型
编码注释:
(常用编码array('ASCII','GB2312','GBK','UTF-8'));
iconv和mb_convert_encoding两个函数的区别:
iconv和mb_convert_encoding两者的区别 在于iconv的效率要比mb_convert_encoding()要高很多, 但是iconv不支持过于复杂的字符;
如:囧之类的,这时候可以使用mb_convert_encoding.
且iconv在转换字符"-"到gb2312时会出错,如果没有ignore参数,所有该字符后面的字符串都无法被保存。
不管怎么样,这个"-"都无法转换成功,无法输出。另外mb_convert_encoding没有这个bug.
多字节字符:
mb_strpost(); 查询字符串首次出现的位置
mb_strlen(); 返回字符串的长度
进制转换
进制转换:
base_convert 在任意进制之间转换数字
dechex 将十进制转换为十六进制
hexdec 将十六进制转换为十进制
decbin 将十进制转换为二进制
bindec 将二进制转换为十进制
pack(); 把数据装进一个二进制字符串.
unpack(); 从二进制字符串对数据进行解包.
加密
加密扩展:
hash() 根据哈希算法生成哈希值
hash_hmac() 使用 HMAC 方法,根据哈希算法生成带有密钥的哈希值
hash_file() 使用给定文件的内容生成哈希值
hash_init() 初始化增量哈希运算上下文
md5() 计算字符串的 MD5 散列值
sha1() 计算字符串的 sha1 散列值
sha1_file() 计算文件的 sha1 散列值
password_hash() 使用足够强度的单向散列算法创建密码的散列(hash)
这个最棒的用法在于,每次生成的hash值是不同的,但是后面password_verify验证的时候都没问题.
比如我注册的时候,以cost为10生成一个存起来.登录的时候验证通过之后,通过password_needs_rehash确认用户记录中的密码hash值
是否过时了,这时候我们可以cost为20重新生成一个更新数据库里的值.
密码的哈希值要存储在数据库的varchar(255)中.便于以后存储比现在的bcrypt算法得到的哈希值更长的密码.
它有三个参数:密码、哈希算法、选项。前两项为必须的。
第三个参数为一个包含有选项的关联数组。目前支持两个选项:salt,在散列密码时加的盐(干扰字符串),以及cost,用来指明算法递归的层数。
返回散列后的密码, 或者在失败时返回 FALSE。
使用的算法、cost 和盐值作为散列的一部分返回。所以验证散列值的所有信息都已经包含在内。 这使 password_verify() 函数验证的时候,不需要额外储存盐值或者算法的信息。
当前支持的算法:
PASSWORD_DEFAULT - 使用 bcrypt 算法 (PHP 5.5.0 默认)。 注意,该常量会随着 PHP 加入更新更高强度的算法而改变。 所以,使用此常量生成结果的长度将在未来有变化。 因此,数据库里储存结果的列可超过60个字符(最好是255个字符)。
PASSWORD_BCRYPT - 使用 CRYPT_BLOWFISH 算法创建散列。 这会产生兼容使用 "$2y$" 的 crypt()。 结果将会是 60 个字符的字符串, 或者在失败时返回 FALSE。
PASSWORD_ARGON2I - 使用 Argon2 散列算法创建散列。
password_verify() 验证密码是否和散列值匹配
它接收2个参数:密码和哈希值,并返回布尔值。检查之前生成的哈希值是否和密码匹配.
密码验证码时,只需要传入密码和哈希值,不用管加密时的算法. 任何算法都可以做验证.
原因在上面的加密部分已经说明了,这里不累述
切记: 登录的时候验证通过之后,通过 password_needs_rehash()确认用户记录中的密码hash值是否已经过时了,
因为我们可能加密的时候采用cost为10,后面改成了20之类的.password_needs_rehash可以同时返回旧密码hash和密码文本
类型转换
强制转换:
(float) 获取变量的浮点值和floatval()相似
(int) 转换成整型和intval()相似
(bool) 转换成布尔型和boolval()相似
(float) 转换成浮点型和floatval();相似
(string) 转换成字符串和strval();相似
(array) 转换成数组
(object) 转换成对象
时间
时间:
time(); 返回Unix时间戳以秒为基础
strtotime(); 将英文格式时间,解析为Unix时间戳
date_diff(); 返回两个日期间的差值
date_format(); 返回根据指定格式进行格式化的日期。
date(); 格式化时间戳
date_default_timezone_get(); 获取由所有的 Date/Time 函数使用的默认时区。
date_default_timezone_set(); 设置由所有的 Date/Time 函数使用的默认时区。
new DateTime(); PHP5.2.0以后推荐使用DateTime类而不是相应的函数,该类可以达到任何时间需要
数学计算
高精度计算心得:
今天做比特币,分叉币转换的时候.出现一个问题, 即高精度计算结果出现错误.如: 正确结果为0.0000001,但是现在是-0.00001或者0之类的,对不上数.
经过逐一排查,发现原来是高精度左右两个数的类型不同, 一侧是科学计数法, 导致结果出现异常.
原因如下:
1. 使用$finance = finance();得到的用户资产是double型(因为finance()中有运算).传到user_financeModel 中的save()方法中后, 变成了科学计数法. 这时候,再使用高精度加减.出现了错误.结果对不上号.
2. save()中的加减, 利用bcadd()函数的加法特性,即正负相加相当于减法.我们用的时候是如bcadd(100,-10,8)这时候第二个参数,因为多了一个符号,变成了科学计数法.
解决办法:
1.所以我们采用, 在save()中使用bcadd(100,-10,8)之前的时候使用bcsub(0,100,8)利用0-正数得到负数的,减法原则,得到一个bc函数可用的字符串负数,进行操作.
2.另外, 利用sprintf();函数也可以将前台传来的数据格式化为浮点型字符串,字符串(前台传来的都是字符串).一般作为开头判断使用.注意注意bc函数的使用的类型的话, 就可以不用sprintf过滤.
数学计算:
注意: 高精度计算左右两侧必须是字符串, 库里查的,前端传的都是字符串, 但是一旦运算后,字符串就被转换了,要注意高精度使用之前不要运算,运算的话, 记得转换为字符串, 要小心使用.
bcscale(); 设置所有bc函数(未设定小数位情况下)的默认小数位数
bccomp(); 比较两个任意精度的数字(如果两个数相等返回0,左边的数比较右边的数大1, 否则-1.)
bcadd(); 2个任意精度数字的加法计算(左操作数和右操作数求和)
bcsub(); 2个任意精度数字的减法(左操作数减去右操作数).
bcmul(); 2个任意精度数字的乘法运算
bcdiv(); 两个任意精度的除法运算;(左操作数除以右操作数)
abs(); 绝对值
ceil(); 进1法取整
floor(); 舍去法取整
fmod(); 浮点数取余
round(); 浮点数四舍五入
max(); 最大值
min(); 最小值
mt_rand(); 更好的随机数
rand(); 随机数
URL
URL:
parse_url(); 解析URL按照组成部分生成关联数组(也可以指定返回URL的那一部分),返回包含但不限于scheme,host,port,path,query等
http_build_query(array); 将数组按照KeyValue, 格式化为查询字符串,第二个参数会在数字下面前添加前缀, 第三个参数用于指定拼接的字符串.该函数会对字符串记性urlencode如果不想encode可以把结果进行urldecode就好.
urlencode(); 编码URL字符出
urldecode(); 解码已编码的URL字符串
get_headers(URL,format); 获取服务器响应一个HTTP请求发送的所有头部信息(format为1时,请求头按照分类,形成关联数组类型的多维数组).
同时该方式也可也获取远程文件的大小等信息(一般响应都里面都有文件类型和文件大小等信息)
getallheaders(); 获取所有的http请求头(Nginx下undefined,20170728,亲测);
HTTP:
setcookie(); 定义与 HTTP 报头的其余部分一共发送的 cookie。
header(); 向客户端发送原始的报文头
headers_sent(); 检查 HTTP 报文头是否发送/已发送到何处。
header_list(); 返回已发送的(或待发送的)响应头部的一个列表。
header();如: #发送原生header头信息
header('HTTP/1.1 200 OK'); # 返回响应信息, 可以通过浏览器状态和ajax查看
header('Location: http://URL'); # 重定向
header('Content-Type: text/html; charset=utf-8'); #设置文件头信息中的编码类型
header('Content-Type: image/jpeg'); # 一般在gd处理图片时设置头信息
header('Content-language: en'); # 设置文档语言
header('Content-Length: 1234'); # 设置内容长度
正则
正则:
# 最常用
preg_match(); 执行一个正则表达式匹配
preg_replace(); 执行一个正则表达式的搜索和替换
# 其他
preg_match_all(); 执行一个全局正则表达式匹配
preg_replace_callback(); 执行一个正则表达式搜索并且使用一个回调进行替换
preg_grep(); 返回匹配模式的数组条目
preg_last_error 返回最后一个PCRE正则执行产生的错误代码
split 用正则表达式将字符串分割到数组中
CLI命令 下常用命令
CLI 下常用命令
命令:
$argv 包含当运行于命令行下时传递给当前脚本的参数的数组。
$argc 包含当运行于命令行下时传递给当前脚本的参数的数目
php -v 查看PHP版本
php -a 进入PHP命令行交互模式,然后在里面使用echo time();之类的即可运行
php -m 查看PHP内置及已加载的扩展模块
php -i PHP详细信息(相当于调用phpinfo()) 通过PHP -i | grep php.ini可以获取PHP.ini的地址)=;
php -i | grep configure 查看PHP编译语句
php -c 路径 指定一个放置php.ini文件的目录,或者直接指定文件.ini.文件名可以叫PHP.ini
php -f 路径 解析并执行指定的文件。-f是可选的,置顶PHP文件时可以不加-f参数;
php -r 'PHP代码' 允许直接在命令行上执行PHP(注意要有引号); php -r '$a="完事了";echo $a.PHP_EOL;'
php -n 完全忽略php.ini
php -l 对指定目录或文件,进行PHP的语法检查
php -s 显示语法高亮源代码。但是高亮代码是用HTML做的,所以命令里输出的结果要存起来用个浏览器看.
php --ini 查看当前PHP 加载的配置文件的数量,路径和信息.
php --ri 扩展名 显示给定扩展的配置信息(由phpinfo()返回的相同信息)
php --rf 函数名 显示函数名信息,或类方法的信息(例如参数的数量和名称)
php --rc 类名 显示给定类的信息(常量、属性和方法的列表)。
php --re 扩展名 显示关于给定扩展的信息(php列表。ini选项、定义函数、常量和类)。
php --rz 显示关于zend的扩展名的信息
php -S localhost:80 -t 指定目录(默认为当前目录) -c 指定php.ini配置文件
在指定目录目录启动一个PHP自带的服务器,可以直接用域名+文件名的形式访问,该方式也可以使用路由
如果要在框架下用这个, 可以直接在框架的引导文件目录启动即可
比如:我在yaf框架用的时候,直接在public目录中运行 php -S localhost:999随后直接访问localhost:999 即可成功
php -S 案例:
// router.php 编写路由文件
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"]))
return false; // 命中, 请求要取文件, 直接返回请求的文件
else {
//否则输出简单的字符串提示
echo "Welcome to PHP
";
}
//启动命令
php -S localhost:999 router.php
系统变量:
访问各个输入/输出流:
STDIN # 获取输入的数据流
STDOUT # 输出数据流,写入到输出缓冲区
STDERR
基本上常用的用法就这样,用的也就这两个:
fwrite(STDOUT, '请输入消息: '); # 在命令行输出,同时提供一个输入框,
$msg = trim(fgets(STDIN)); # 获取输入框输入的内容
var_dump($msg);
系统函数
函数:
memory_get_usage(bool) 返回当前分配给你的 PHP 脚本的内存量,单位是字节(byte)。
如果设置为 TRUE,获取系统分配总的内存尺寸,包括未使用的页。如果未设置或者设置为 FALSE,仅仅报告实际使用的内存量。
get_defined_vars() 获取当前作用域/符号表中定义的所有变量
function_exists() 在已经定义的函数列表(包括系统自带和用户自定义)中查找函数名。
func_get_arg 返回参数列表的某一项
func_get_args 返回一个包含函数参数列表的数组
func_num_args 返回传递到目前定义函数的参数数目
get_defined_functions 返回所有已定义函数的数组
register_shutdown_function 注册一个会在php中止时执行的函数
call_user_func 把第一个参数作为回调函数调用,其余参数是回调函数的参数.
call_user_func_array 把第一个参数作为回调函数调用,并把一个数组参数作为回调函数的参数.
register_shutdown_function 当进程停止时被调用的函数
filter_var 使用特定的过滤器过滤一个变量
filter_var_array 获取多个变量并且过滤它们
filter_input 通过名称获取特定的外部变量,并且可以通过调用过滤器处理它
如:filter_input(INPUT_POST,'email',FILTER_VALIDATE_EMAIL)验证POST提交的email字段,通过邮箱验证的格式
filter_input_array (和上面一样不过是可以处理一个数组)
本函数可从各种来源获取输入:
INPUT_GET
INPUT_POST
INPUT_COOKIE
INPUT_ENV
INPUT_SERVER
INPUT_SESSION (Not yet implemented)
INPUT_REQUEST (Not yet implemented)
错误处理
error_get_last(); 返回了一个关联数组,获取关于最后一个发生的错误的信息。
在PHP同目录下的, PHP错误等级设置 篇中有详细介绍
ini_set('display_errors',1); //显示错误信息
ini_set('display_startup_errors',1); //php启动错误信息
# 是否打印错误信息到浏览器/命令行界面
# 开发模式下建议开启,产品模式下强烈建议关闭
ini_set('display_errors', 'On');
# 是否记录错误信息到日志
# 开发模式和产品模式下都建议开启
ini_set('log_errors', 'On');
# 指定错误信息日志文件,若开启了 log_errors 选项,记得指定日志文件位置
# 要确保执行 php 脚本的系统用户拥有该文件的 write 权限,否则日志无法被写入
ini_set('error_log', '/usr/local/php/errors.log');
# 该选项用以设定错误报告的等级
# 等同于 error_reporting(E_ALL)
# 无论开发模式还是产品模式下都建议开到E_ALL(报告所有的错误信息)
# 产品模式下也需要设置此选项,因为关闭了 display_errors 并开启了 log_errors
# 所以浏览器/命令行界面不会因此暴露报错信息
ini_set('error_reporting', E_ALL);
ini_set('error_reporting', E_ALL); 和 error_reporting(E_ALL); 一样
error_log ( string $message [, int $message_type = 0 [, string $destination [, string $extra_headers ]]] ) : bool
把错误信息发送到 web 服务器的错误日志,或者到一个文件里。
发送到邮箱的时候,需要在php.ini中配置邮箱服务.具体的搜索 error_log配置邮箱
message
应该被记录的错误信息。
message_type
设置错误应该发送到何处。可能的信息类型有以下几个:
0默认 message 发送到 PHP 的系统日志,使用 操作系统的日志机制或者一个文件
1 message 发送到参数 destination 设置的邮件地址。
2 废弃
3 message 被发送到位置为 destination 的文件里。 字符 message 不会默认被当做新的一行。
4 message 直接发送到 SAPI 的日志处理程序中。
destination
目标,可以是一个路径。它的含义描述于以上,由 message_type 参数所决定。
extra_headers
额外的头。当 message_type 设置为 1 的时候使用。 该信息类型使用了 mail() 的同一个内置函数。
设置错误报告级别的方法:
error_reporting(-1); // 函数能够在运行时设置 error_reporting 指令。
PHP 有诸多错误级别,使用该函数可以设置在脚本运行时的级别。如果没有设置可选参数 level,error_reporting() 仅会返回当前的错误报告级别。
选项
& 表示并且
| 表示或者
~ 表示除了
^ 表示除了
error_reporting(); 设置报错级别;
说明:
E_ERROR 1
E_WARNING 2
E_NOTICE 8
常用设置例如:
//关闭错误报告
error_reporting(0);
//报告 runtime 错误
error_reporting(E_ERROR | E_WARNING | E_PARSE);
//报告所有错误
error_reporting(E_ALL);
//等同 error_reporting(E_ALL);
ini_set("error_reporting", E_ALL);
//报告 E_NOTICE 之外的所有错误
error_reporting(E_ALL & ~E_NOTICE);
//除了NOTICE,其他都报:
error_reporting(E_ALL & ~E_NOTICE);
error_reporting(E_ALL ^ E_NOTICE);
//报告所有 PHP 错误:
error_reporting(E_ALL);
error_reporting(-1);
//关闭所有PHP错误报告
error_reporting(0);
// 报告 E_NOTICE也挺好 (报告未初始化的变量
// 或者捕获变量名的错误拼写)
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
1. 修改PHP的配置文件php.ini
这种方式设置error_reporting后,重启web服务器,就会永久生效。
这里以xampp集成软件包为例,打开配置文件php.ini,查看错误报告级别error_reporting的默认值,如下:
error_reporting=E_ALL & ~E_DEPRECATED & ~E_STRICT
意思是报告所有的错误,但除了E_DEPRECATED和E_STRICT这两种。
将其修改为:
error_reporting=E_ALL & ~E_NOTICE
意思是报告所有的错误,但除了E_NOTICE这一种。这也是最常用的错误报告级别,它不会报告注意类(如:使用了未定义的变量)的错误。
保存,重启web服务器后生效。
2. 使用error_reporting()函数
这种方式设置后,可以立即生效。但仅限于在当前脚本中的error_reporting()函数调用的后面区域。
int error_reporting ([ int $level ] )
参数可以是整型或对应的常量标识符,推荐使用常量的形式。返回值为当前位置处起作用的错误报告级别的值(整型值)。
下面列举一些错误报告级别:
值 常量 说明
1 E_ERROR 报告导致脚本终止运行的致命错误
2 E_WARNING 报告运行时的警告类错误(脚本不会终止运行)
4 E_PARSE 报告编译时的语法解析错误
8 E_NOTICE 报告通知类错误,脚本可能会产生错误
32767 E_ALL 报告所有的可能出现的错误(不同的PHP版本,常量E_ALL的值也可能不同)
error_reporting(E_ALL ^ E_NOTICE); // 除了E_NOTICE之外,报告所有的错误
error_reporting(E_ERROR); // 只报告致命错误
echo error_reporting(E_ERROR | E_WARNING | E_NOTICE); // 只报告E_ERROR、E_WARNING 和 E_NOTICE三种错误
注意:配置文件php.ini中display_errors的默认值为On,代表显示错误提示,如果设置为Off,就会关闭所有的错误提示。
使用 error_reporting(0) 或者在函数前面加 @,可以抑制错误输出,以防止错误消息泄露敏感信息。
JSON和数组转换
json_encode($value,$option); # 将数组转换为JSON格式, 函数仅能处理 UTF-8 编码的数据
json_decode($string, [bool]); # 将一个Json字符串转换为对象/数组, 函数仅能处理 UTF-8 编码的数据
json_last_error # 返回最后一次Json编码/解码的错误,如果有的话.
调用外部系统shell
shell_exec(); # 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
`系统命令`; # 执行运算符,和shell_exec()一样.反引号运算符在激活了安全模式或者关闭了 shell_exec() 时是无效的。
system(); # 执行外部程序,并且显示输出和exec()一样都是有第二个值的,用的时候要注意
exec(); # 执行一个外部程序和system()一样都是有第二个值的,用的时候要注意
其他
其他:
&变量名 取值符, 作为引用传值用
注意:
1、只有变量才能引用。
2、引用后一个变量发生变化另外一个变量也会发生变化。
3、引用传值后unset掉一个变量,只是解除了引用关系。
$$变量名 可变变量
可变变量的案例:
$Bar = "a";
$Foo = "Bar";
$World = "Foo";
$Hello = "World";
$a = "Hello";
$a; //Returns Hello
$$a; //Returns World
$$$a; //Returns Foo
$$$$a; //Returns Bar
$$$$$a; //Returns a
$$$$$$a; //Returns Hello
$$$$$$$a; //Returns World
DIRECTORY_SEPARATOR 在不同系统下自动匹配正斜线或反斜线
PHP_EOL; 不同系统自动调整为\r\n或者\n的换行符
ini_set(); 设置配置参数
ini_get(); 获取配置参数
ini_get_all(); 获取所有配置信息
ini_restore(); 配置信息重置所有到原始状态
isset(); # 判断变量是否存在
DIRECTORY_SEPARATOR # 系统自带'/'符号的常量,
set_time_limit(0) # 设置允许脚本运行的时间,单位为秒。
trigger_error('message', E_USER_ERROR); # 函数创建用户级别的错误消息。
eval(); # 把字符串按照PHP代码来运行;
phpversion(); # 查看PHP版本号
constant(); 返回一个常量的值。
define(); 定义一个常量
defined(); 检查常量是否存在
eval(); 把字符串按照PHP代码来运行.
highlight_file(); 对文件语法进行高亮
show_source(); highlight_file() 的别名。
sleep(); 延迟执行代码若干秒.
usleep(); 延迟执行代码若干微妙.
time_nanosleep(); 延迟代码执行若干秒和纳秒。
time_sleep_until(); 延迟代码执行指定时间.
uniquid(); 生成唯一ID
预定义变量即超全局变量
预定义变量:
session_save_path(); # 查看session保存的位置也可以用来设置
stream_context_create(); # 创建资源流上下文
set_time_limit(); # 设置脚本最大执行时间
stream_filter_append(); # 将filtername添加到附加到流的过滤器列表中。
stream_filter_register(); # 允许您在与所有其他文件系统函数(如fopen()、fread()等)一起使用的任何注册流上实现的 自定义流过滤器过滤器类。
# 注册完毕后可以在后面可以使用stream_filter_append调用.具体使用方法,可以在流处理的笔记中查看.
memory_get_usage(); # 返回当前分配给你的 PHP 脚本的内存量,单位是字节(byte)。放在脚本最后调用.
realpath_cache_size(); # 获取真实路径缓存区大小在内存中的使用量。
realpath_cache_get(); # 获取真实目录缓存的详情
__spl_autoload_register(); # 自动加载类和接口(CLI下不可用); 严格来讲这个不算魔术方法.
putenv(); # 设置系统变量
getenv(); # 获取系统变量
unset(); # 函数是用来销毁变量的,若要释放内存可以用$变量=null.在销毁数组的指定的值时,数组将保持原有索引关系
var_dump(); # 此函数显示关于一个或多个表达式的结构信息,包括表达式的类型与值。数组将递归展开值,通过缩进显示其结构.
var_export(); # 和 var_dump() 类似,不同的是其返回的表示是合法的 PHP 代码
debug_backtrace(); # 产生一条回溯跟踪,数组(跟踪程序调用以及传参,自身是第一个键,以此类推)
debug_print_backtrace();# 打印一条回溯,直接把追溯的结果输出打印出.
get_defined_constants();# 返回所有常量关联数组(包含define和扩展中的)键是常量名,值是常量值;
PHP_SAPI #返回访问PHP的类型小写字符串(CLI或FPM或其他,apache下可能有所不同);
php_sapi_name(); # 返回web服务器和PHP之间的接口类型(同上);
$GLOBALS # 超全局变量 以数组形式使用,与所有其他超全局变量不同,$GLOBALS在PHP中总是可用的。
$GLOBALS['HTTP_RAW_POST_DATA'] # (PHP7已弃用用下面这个)总是产生 $HTTP_RAW_POST_DATA 变量包含有原始的 POST 数据。此变量仅在碰到未识别 MIME 类型的数据时产生。$HTTP_RAW_POST_DATA 对于 enctype="multipart/form-data" 表单数据不可用。补充说明:PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型。也就是说基本上$GLOBALS['HTTP_RAW_POST_DATA'] 和 $_POST是一样的,但是有一点是不一样的,$_POST只能将接收到的application/x-www.form-urlencoded转换为数组,其他类型接为空了,而且这个函数接收到的如果是普通的POST请求,会是原始的XXX=XXX&OOO=OO形式。如果post过来的数据不是PHP能够识别的,你可以用 $GLOBALS['HTTP_RAW_POST_DATA']来接收,比如 text/xml 或者 soap 等等,就可以用这个函数来获得原始请求数据。补充说明:PHP默认识别的数据类型是application/x-www.form-urlencoded标准的数据类型。
file_get_contents('php://input'); # 可以用来替代$GLOBALS['HTTP_RAW_POST_DATA'],另外php://input 也可以实现上面这个功能.php://input 允许读取 POST 的原始数据。和 $HTTP_RAW_POST_DATA 比起来,它给内存带来的压力较小,并且不需要任何特殊的 php.ini 设置。php://input 不能用于 enctype="multipart/form-data"。
$_POST # 当 HTTP POST 请求的 Content-Type 是 application/x-www-form-urlencoded 或 multipart/form-data 时,会将变量以关联数组形式传入当前脚本。
$_GET # 通过 URL 参数传递给当前脚本的变量的数组。
global # 全局变量, 需要引用外部变量时,在变量前global $variable即可;
$_REQUEST # HTTP REquest变量, 默认保存了$_GET $_POST $_COOKIE的数组
$http_response_header # 获取请求返回的响应头,比如如:file_get_contents()之后使用
ArrayAccess # 提供像访问数组一样访问对象的能力的接口
__LINE__ # 获取当前代码行
__FILE__ # 获取当前文件的路径(精确到当前文件)
__DIR__ # 获取当前文件的文件夹地址
__METHOD__ # 返回当前方法被定义时的名字
__CLASS__ # 返回当前类被定义时的名字
__FUNCTION__ # 返回当前函数被定义时的名字
__NAMESPACE__ # 返回当前命名空间被定义时的名字
realpath # 返回绝对路径名同时会删除所有的符号连
get_class() # 获取当前语句所在类的类名
get_class_methods() # 获取类的所有方法名
get_class_vars() # 获取类的所有的变量名
method_exists() # 检查指定类的指定方法是否存在
class_exists() # 检查指定类是否已被定义
$_SERVER:
$_SERVER['HTTP_ACCEPT_LANGUAGE'] # 请求头中Accept_language中自然语言的类型
$_SERVER['HTTP_HOST'] # 获取当前域名
$_SERVER['REQUEST_URI'] # 获取要访问的页面URL(域名后的URL)
$_SERVER['REQUEST_METHOD'] #访问页面时的请求方法 get/post
$_SERVER['QUERY_STRING'] # 获取查询字符串
$_SERVER['HTTP_USER_AGENT'] # 当前请求的 User_Agent: 头部的内容
# 下面三者通常合在一起使用,用以捕捉用户相对真实的IP地址(通过循环判断)
$_SERVER['REMOTE_ADDR'] # 当前访问页面用户的IP
$_SERVER['HTTP_X_FORWARDED_FOR'] # 获取访问用户的网关 (如果用户没开代理, 该项不显示)
$_SERVER['HTTP_CLIENT_IP'] # 获取客户端的IP (如果用户没开代理,该项不显示)
$_SERVER['SERVER_NAME'] # 当前运行脚本所在服务器主机的名称。
$_SERVER['SERVER_ADDR'] # 当前运行脚本的服务器IP
$_SERVER['REMOTE_PORT'] # 用户连接到webu服务器所用的端口号
$_SERVER['SCRIPT_FILENAME'] # 当前执行脚本的绝对路径
$_SERVER['SERVER_PORT'] # web服务器使用的端口
$_SERVER['REQUEST_SCHEME'] # URL协议名称返回小写的http或者https
$_SERVER['HTTPS'] # HTTPS协议时存在,否则不存在
小计:
通过对$_SERVER进行遍历, 匹配含有'HTTP'字段的所有数组, 可以获得所有请求头.但并不是所有的请求头都带有HTTP_开头,所有需要单独匹配CONTENT_LENGTH, CONTENT_TYPE等等, 具体请百度.
自定义请求头中会自动加上HTTP开头的字符串, 自定义请求头不支持'_',但是支持'-';
getallheaders();获取所有请求头, 官方说支持,但是亲测在Nginx,PHP7,MacX下不好使. -20170728
缓冲区处理
ob_start 打开输出缓冲区,无论php.ini的文件如何配置,如果使用该函数,即使output_buffering设置成off,也会打开输出缓冲区
ob_start函数还接受一个参数,该参数是一个函数的回调,意思是,在输入缓冲区内容之前,需要使用调用传递进来的参数把缓冲区的内容处理一次,再放入缓冲区内
ob_flush 指示php本身刷新自身的缓冲区,把数据发送到apache
flush 作用是发送指令到apache,让apache刷新自身的输出缓冲区.
ob_implicit_flush 作用和implicit_flush一样,是否自动刷新apache的缓冲区
ob_end_flush 把php自身的缓冲区里的内容发送到apache,并把清除自身缓冲区内的内容
ob_get_flush 获取缓冲区里的内容,并且把这些内容发送到apache
ob_list_handlers 获取运行ob_start时,所回调的函数名称, 例如:
ob_start(‘ob_gzhandler’);
print_r(ob_list_handlers);
将打印出ob_gzhandler;
ob_gzhandler 该函数的作用是作为ob_start的回调参数, 在缓冲区刷新之前,会调用该函数对数据进行到底gzip或者deflate压缩.这个函数需要zlib扩展的支持.
ob_get_contents 获取输出缓冲区里的内容
ob_get_length 获取缓冲区里内容的长度
ob_get_clean 获取缓冲区的内容之后,清除缓冲区.
ob_clean 清空php缓冲区里面的内容
ob_end_clean 清空php缓冲区内的内容,并且关闭输出缓冲区
与输出缓冲区有关的配置
在PHP.INI中,有两个跟缓冲区紧密相关的配置项
1.output_buffering
该配置直接影响的是php本身的缓冲区,有3种配置参数.on/off/xK(x为某个整型数值);
on - 开启缓冲区
off - 关闭缓冲区
256k - 开启缓冲区,而且当缓冲区的内容超过256k的时候,自动刷新缓冲区(把数据发送到apache);
2.implicit_flush
该配置直接影响apache的缓冲区,有2种配置参数. on/off
on - 自动刷新apache缓冲区,也就是,当php发送数据到apache的缓冲区的时候,不需要等待其他指令,直接就把输出返回到浏览器
off - 不自动刷新apache缓冲区,接受到数据后,等待刷新指令
使用缓冲区的相关内容
Nginx环境下PHP flush失效的解决方法
fastcgi_buffer_size 128k;
fastcgi_buffers 8 128k;
Nginx会缓冲PHP输出的信息,当达到128k时才会将缓冲区的数据发送给客户端,那么我们首先需要将这个缓冲区调小
比如:
fastcgi_buffer_size 4k;
fastcgi_buffers 8 4k;
必须禁用gzip
gzip off;
然后,在php中,在ob_flush和flush前,输出一段达到4k的内容,例如:
echo str_repeat(‘ ‘, 1024*4);
到此,PHP就可以正常通过ob_flush和flush逐行输出需要的内容了。
想要了解PHP的缓冲区,就要知道执行PHP的时候,缓冲区被设置到了什么地方.
当执行PHP的时候,如果碰到了echo print_r之类的会输出数据的代码,PHP就会将要输出的数据放到PHP自身的缓冲区,等待输出.
当PHP自身的缓冲区接到指令,指示要输出缓冲区的内容时,将会把缓冲区内的数据输出到apache上, apache接受到PHP输出的数据,然后再把该数据存在到apache自身的缓冲区内,等到输出
当apache接受到指令,只是要输出缓冲区的内容时, 将会把缓冲区的内容输出,返回到浏览器.
步骤:执行php---->(碰到echo,print_r之类输出)将输出的数据放到php自身的缓冲区,等待输出---->(接收输出缓冲区内容)数据输出到apache上,存入apache自身的缓冲区---->(接收输出指定)缓冲区内容输出,返回到浏览器
echo、print => php output_buffering => webServer buffer => browser buff => browser display
即:脚本输出 => php的缓冲区设置 => 系统的缓冲区设置(apache、nginx) => 浏览器的缓冲区设置 => 显示给用户
由此可见,PHP要输出数据的时候,将会经过两个缓冲区(先是自身的,然后是apache的),再返回到浏览器.
1.ob_flush和flush的次序关系.上面的分析可以看出,ob_flush是和php自身相关的,而flush操作的是apache的缓冲区,所有我们在使用这两个函数的时候,需要先执行ob_flush,再执行flush,因为我们需要先把数据从PHP上发送到apache,然后再由apache返回到浏览器.如果php还没有把数据刷新到apache,就调用了flush,则apache无任何数据返回到浏览器.
2.有的浏览器,如果接受到的字符太少,则不会把数据显示出来,例如老版的IE(必须要大于256k才显示).这样就会造成一个疑问, 明明在php和apache都进行了刷新缓冲区的操作,但是浏览器就是没有出现自己想要的数据,也许就是这个原因造成的.所以才测试的时候,可以在输出数据的后面加上多个空格,以填满数据,确定不会浏览器造成这类诡异的问题.
3.有些webserver,他自身的输出缓冲区会有一些限制,比如nginx,他有一个配置fastcgi_buffer_size 4k, 就是是表明,当自身的输出缓冲区的内容达到4K才会刷新,所以为了保证内容的数据,可以添加以下代码,保证内容长度
4.在apache中,如果你开启了mod_gzip的压缩模块,这样可能会导致你的flush函数刷新不成功,其原因是,mod_gzip有自己的输出缓冲区,当php执行了flush函数,指示apache刷新输出缓冲区,但是内容需要压缩,apache就把内容输出到自身的mod_gzip模块,mod_gzip也有自身的输出缓冲区,他也不会马上输出,所以造成了内容不能马上输出.为了改善这个情况,可以关闭mod_gzip模块,或者在httpd.conf增加以下内容,以禁止压缩
文件处理和网络请求
文件处理:
PHP的文件文件请求,几乎都可以作为网络请求使用.比如fopen();file_get_contents();等
stream_get_meta_data(); # 从封装协议文件指针中取得报头/元数据,返回现有 stream 的信息。可以是任何通过 fopen(), fsockopen() 和 pfsockopen() 建立的流。下面有案例
stream_set_timeout(); # 作用于读取流时的时间控制。fsockopen函数的timeout只管创建连接时的超时,对于连接后读取流时的超时,则需要用到 stream_set_timeout函数。下面有案例
stream_set_blocking() # 为资源流设置阻塞或者阻塞模式
mkdir(); #新建目录,第二个参数为设置权限首位补0如:0777,第三个参数为true为递归创建.
chmod(); #修改文件权限,第二个参数权限位参数首位必须补0如:0777
dir(); #打开目录(也可以当前类来用如:$dir=dir(目录);$file=$dir->read();$dir->close())
readdir(); #读取目录
pathinfo(); #返回文件的路径信息
basename(); #返回路径中的文件名部分
dirname(); #返回路径中的目录部分
touch(); #创建一个空文件,如果文件已经存在的话那么更新访问时间和修改时间。
file(); #将整个文件读取到数组中,每一行作为数组中的一个元素。
unlink(); #删除文件
rmdir(); #删除目录
rname(); #重命名
copy(); #复制文件
stat(); #给出文件信息
filesize(); #取得文件大小,获取远程文件的大小用get_headers,获取响应头来处理
filetype(); #取得文件类型,获取远程文件的类型用get_headers,获取响应头来处理
fileatime(): #取得文件的上次访问时间
tilectime(): #取得文件的 inode 修改时间(作为创建时间是不错的);
filemtime(): #取得文件修改时间
file_put_contents(); #将一个字符串写入到文件中(追加或覆盖模式)
file_get_contents(); #将整个文件的内容读取到一个字符串中,或者发送网络请求,配合stream_context_create修改请求头什么可以发送POST上传文件.
file_get_contents('php://input'); #可以用来接收Content-Type: text/json(即Chrome中request_payload)等形式的请求参数,或者未标识请求头的数据.
$http_response_header; #获取HTTP的响应头,在file_get_contents()调用URL之后可以用来获取.其他的地方还没发现有用到.
get_headers() #获取服务器响应一个 HTTP 请求头,第二个参数为true时返回关联数组。
is_writeable(); #判断文件是否可写
is_readable(); #判断文件名是否可读
is_executable(); #判断文件名是否可执行
is_dir(); #判断是否是一个目录
is_file(); #判断是否是一个文件
file_exists(); #判断文件或目录是否存在
注释:
记住 PHP 也许只能以运行 webserver 的用户名(通常为 'nobody')来访问文件。不计入安全模式的限制。
1、打开文件获得资源
fopen('文件位置','模式'); # 开一个文件资源,也可以是一个URL链接地址
模式:
r:只读方式打开。文件指针指向文件头。文件不存在将报错。
r+:读写方式打开,文件指针指向文件头部。文件不存在将报错。(新内容依次从文档开头进行覆盖。)
w:写入方式打开,将文件指针指向文件头部并且将文件大小截取为零,如果文件不存在就创建。
w+:读写方式打开,将文件指针指向文件头部并且将文件大小截取为零,如果文件不存在就创建。
a:写入方式打开,文件指针指向文件末尾。文件不存在就创建。
a+:读写方式打开,将文件指针指向末尾,如果文件不存在就创建。
2、操作文件
feof(资源); 函数检测是否已到达文件末尾 (eof)。
fgets(资源); 一次读取一行指针下移 到文件最后返回false
fgetc(资源); 一次读取一个字符,指针下移
fread(资源, 字符数)依次读取指定个数的字符,指针下移。
fwrite(资源,写入的内容);将内容写入到文件指针处。
fgetcsv(资源,长度) 从文件指针中读取一行csv字段
fputcsv(资源,数组) 将数据格式化为csv格式并写入文件
3、关闭资源
fclose(资源);
由于国内的网络环境不是很稳定,尤其是连接国外的时候,不想程序出现Fatal error: Maximum execution time of 30 seconds exceeded in …的错误,该函数尤其有用。stream_set_timeout需配合stream_get_meta_data使用,如果没有timeout, stream_get_meta_data返回数组中time_out为空,反之为1,可根据此判断是否超时。另外由于PHP默认的Maximum execution time为30秒,这是一次执行周期的时间,为了不出现上述的Fatal error,还需要设置一个总的读取流的时间,具体方法参见下面详细代码。
$server = "www.yahoo.com";
$port = 80;
$data = "GET / HTTP/1.0rn";
$data .= "Connection: Closern";
$data .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)rnrn";
$start_time = time();
$fp = fsockopen($server, $port, $errno, $errstr, 5);
if (!$fp) {
die("Connect Timeout.n");
} else {
stream_set_blocking($fp, true);
stream_set_timeout($fp, 3);
fputs($fp, "$data");
$text = '';
while (!feof($fp)) {
$text .= fread($fp, 2000);
$diff = time() - $start_time;
if ($diff > 24) {
die("Timeout!n");
}
$status = stream_get_meta_data($fp);
if ($status['timed_out']) {
die("Stream Timeout!n");
}
}
}
fclose($fp);
fsockopen — 打开一个网络连接或者一个Unix套接字连接
可以通过stream_get_transports()来获取套接字传输器支持类型。
stream_socket_client()与之非常相似,而且提供了更加丰富的参数设置,包括非阻塞模式和提供上下文的的设置。
fsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] ) : resource
初始化一个套接字连接到指定主机(hostname)。
如果主机(hostname)不可访问,将会抛出一个警告级别(E_WARNING)的错误提示。
hostname
如果安装了OpenSSL,那么你也许应该在你的主机名地址前面添加访问协议ssl://或者是tls://,从而可以使用基于TCP/IP协议的SSL或者TLS的客户端连接到远程主机。
port
端口号。如果对该参数传一个-1,则表示不使用端口,例如unix://。
errno
如果errno的返回值为0,而且这个函数的返回值为FALSE,那么这表明该错误发生在套接字连接(connect())调用之前,导致连接失败的原因最大的可能是初始化套接字的时候发生了错误。
errstr
错误信息将以字符串的信息返回。
timeout
设置连接的时限,单位为秒。
注意:
如果你要对建立在套接字基础上的读写操作设置操作时间设置连接时限,请使用stream_set_timeout(),fsockopen()的连接时限(timeout)的参数仅仅在套接字连接的时候生效。
返回值
fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。
如果调用失败,将返回FALSE。
请求案例:
GET请求
$host = 'www.baidu.com';
$url = '/';
$handler = fsockopen($host, '80', $errno, $errstr, 5);
stream_set_timeout($handler, 2);
//拼装请求头,发送请求
$header = "GET ${url} HTTP/1.1\r\n";
$header .= "Host: ${host}\r\n";
$header .= "Connection:close\r\n\r\n";
fwrite($handler, $header);
//循环逐行获取返回内容,返回内容包括响应头信息
$response = '';
while ($row = fgets($handler)) {
$response .= $row;
$status = stream_get_meta_data($handler);
if ($status['timed_out']) {
die("Stream Timeout!n");
}
}
//打印信息(返回信息会包括所有的响应头信息,在开头显示)
print_r($response);
POST请求
$host = 'www.example.com';
$port = 80;
$errno = '';
$errstr = '';
$timeout = 5;
$url = '/nihao.php';
$param = [
'name' => 'fdipzone',
'gender' => 'man',
'photo' => file_get_contents('photo.jpg')
];
// 创建连接
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
// 拼装POST请求头,请求内容,发送请求
$data = http_build_query($param);
$out = "POST ${url} HTTP/1.1\r\n";
$out .= "Host:${host}\r\n";
$out .= "Content-type:application/x-www-form-urlencoded\r\n";
$out .= "Content-length:".strlen($data)."\r\n";
$out .= "Connection:close\r\n\r\n";
$out .= "${data}";
fwrite($fp, $out);
// 分段获取响应内容,每次获取4096
$response = '';
while($row=fread($fp, 4096)){
$response .= $row;
$status = stream_get_meta_data($fp);
if ($status['timed_out']) {
die("Stream Timeout!n");
}
}
// 关闭连接,打印内容
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
$response = substr($response, $pos+4);
echo $response;
POST上传文件
'fdipzone',
'gender' => 'man',
);
$file_data = array(
array(
'name' => 'photo',
'filename' => 'photo.jpg',
'path' =>'photo.jpg'
)
);
// create connect
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
// send request
srand((double)microtime()*1000000);
$boundary = "---------------------------".substr(md5(rand(0,32000)),0,10);
$data = "--$boundary\r\n";
// form data
foreach($form_data as $key=>$val){
$data .= "Content-Disposition: form-data; name=\"".$key."\"\r\n";
$data .= "Content-type:text/plain\r\n\r\n";
$data .= rawurlencode($val)."\r\n";
$data .= "--$boundary\r\n";
}
// file data
foreach($file_data as $file){
$data .= "Content-Disposition: form-data; name=\"".$file['name']."\"; filename=\"".$file['filename']."\"\r\n";
$data .= "Content-Type: ".mime_content_type($file['path'])."\r\n\r\n";
$data .= implode("",file($file['path']))."\r\n";
$data .= "--$boundary\r\n";
}
$data .="--\r\n\r\n";
$out = "POST ${url} HTTP/1.1\r\n";
$out .= "Host:${host}\r\n";
$out .= "Content-type:multipart/form-data; boundary=$boundary\r\n"; // multipart/form-data
$out .= "Content-length:".strlen($data)."\r\n";
$out .= "Connection:close\r\n\r\n";
$out .= "${data}";
fputs($fp, $out);
// get response
$response = '';
while($row=fread($fp, 4096)){
$response .= $row;
}
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
$response = substr($response, $pos+4);
echo $response;
?>
';
echo 'gender='.$gender.'
';
if(move_uploaded_file($_FILES['photo']['tmp_name'], UPLOAD_PATH.'/'.$filename)){
echo '';
}
?>
解压缩操作
解压缩操作:
使用PHP进行解压ZIP文件操作需要添加ZIP扩展,PHP7.0是默认添加的.
zip_open 打开ZIP存档文件
zip_read 读取ZIP存档文件中下一项
zip_entry_compressedsize 检索目录项压缩过后的大小
zip_entry_compressionmethod 检索目录实体的压缩方法
zip_entry_filesize 检索目录实体的实际大小
zip_entry_name 检索目录项的名称
zip_entry_open 打开用于读取的目录实体
zip_entry_read 读取一个打开了的压缩目录实体
zip_entry_close 关闭目录项
zip_close 关闭一个ZIP档案文件
注释:
在进行解压操作时,需要按照顺序进行操作
1.zip_open(); 打开ZIP压缩包.
2.zip_read(); 读取ZIP压缩包.
3.zip_entry_name(); 读取压缩包内文件的名称
4.如果必要则进行转码(一般我都会转码文件名为utf-8. 如:iconv('gbk', 'utf-8', zip_entry_name($zRead)));
5.zip_entry_filesize(); 获取压缩包中文件的大小
6.一般情况下,Mac生成的解压包中会含有__MACOSX/的无效文件,WIN下应该也会有但是没测试, 需要使用strstr()过滤掉.
7.zip_entry_open(); 打开压缩包内的文件
8.zip_entry_read(); 读取压缩包内的文件.
9.如果必要,可以使用mkdir建立一个目录,目录名称为ZIP文件名,解压的文件都放这里面去.
10.file_put_content(); 将读取的文件内容写入一个心得文件.
11.close_entry_close(); 关闭读取压缩包内文件的资源
12.zip_close(); 关闭ZIP资源
需要注意的是即使ZIP包内只有一个文件, 在zip_read的时候应该使用while()循环,
如:while($zRead = zip_read($zOpen)){}
因为,首先ZIP包内的文件确定不是单一的,这个时候只要ZIP包内部还有文件或者目录在while()即为真,不断循环.
如:Mac下不仅有需要的文件, 还会有__MACOSX/和__MACOSX/.文件名'两个目录;
使用PHP进行压缩操作,主要使用ZipArchive()类进行压缩操作,PHP5.2以上无需再额外安装扩展.
该类, 同时也可以进行解压操作
解压常用方法:
$zip = newZipArchive(); 初始化该类
$zip->open('置顶文件'); 打开该文件
$zip->extractTop('指定目录'); 解压到置顶目录,MAC中也会生成__MACOSX/.文件名目录.应该进行删除.
$zip->close(); 关闭资源
注释解压完成后, 目录中会生成__MACOSX/.文件名的目录,里面也有一个文件, 是乱码. 需要进行删除.
压缩常用方法:
$zip = newZipArchive(); 初始化该类
$zip->open(路径,状态); 打开ZIP文件,同时设定ZIPARCHIVE::CREATE状态(文件不存在即创建)
$zip->addEmptyDir(文件名); 在压缩包内新建一个空文件夹
$zip->addFromString(文件名,内容); 添加一段文字到ZIP内,同时在ZIP内新建该文件.
$zip->addFile(路径,文件名); 将路径指定的文件,保存在ZIP内,命名为指定的文件名.
$zip->numFiles; 输出压缩包内共有多少个文件
$zip->close($zip); 关闭资源
注释:
使用addEmptyDir一般用于压缩文件时使用.在新建的压缩包中,新建一个空的文件夹.但是用法比较少,
因为大多数情况下, 在压缩之前,就已经设置好文件夹了.我一般会用于在新建压缩包时, 在ZIP中建立一个
空的文件夹, 然后将所有文件放进去.这样以后解压出来的文件, 也会在一个文件夹里, 而不是散开的.
我看到官方手册上, 可以使用
面向对象
use 用来引入命令空间以及在匿名函数之后为匿名函数增加参数,引入外部变量
const 定义一个常量
const和defind()定义常量的区别:
const(一般在类中使用该函数,可以被子类继承.5.3之前只能在类内使用,在编译时定义的, 所以不支持变量, 比较,数学,位运算,同时必须放在最顶端的作用区域,也就意味着不能在函数,if,循环内定义)
defind(一般在类外使用该函数,不可作为类的成员属性使用,在执行该函数时定义的, 因此可以放在函数,循环,if等任何可以被调用的地方,甚至做简单的运算);
# 变长参数列表:
func_get_args(); 获得函数中所有实参的集合。
func_get_arg(第几个参数); 用来获得函数中的第几个参数的值。
func_num_args(); 获得实参的个数。
# 常用来调用的系统函数
function_exists(); 判断一个函数是否存在
get_called_class() 获取静态方法调用的类名。
get_parent_class() 返回对象或类的父类名
get_class() 返回对象的类名
get_parent_class() 返回对象或类的父类名
is_subclass_of() 如果此对象是该类的子类,则返回 TRUE
class_exists() 检查类是否已定义
class_alias() 为一个类创建别名
get_parent_class() 返回对象或类的父类名
interface_exists() 检查接口是否已被定义
is_a() 如果对象属于该类或该类是此对象的父类则返回 TRUE
method_exists() 检查类的方法是否存在
property_exists() 检查对象或类是否具有该属性
call_user_method() 对特定对象调用用户方法
call_user_method_array()以参数列表的数组,调用用户方法
get_declared_classes() 返回由已定义类的名字所组成的数组
get_declared_interfaces()返回一个数组包含所有已声明的接口
get_declared_classes() 返回由已定义类的名字所组成的数组
is_subclass_of() 如果此对象是该类的子类,则返回 TRUE
trait_exists() 检查指定的 trait 是否存在
get_object_vars() 返回由对象属性组成的关联数组
常用系统函数:
serialize(); 序列化对象,把对象生成一个包含字节流的字符串来标识.
unserialize(); 反序列化对象, 把一个包含字节流的字符串返回为PHP原来的值.
method_exists(); 检查指定的类, 是否存在该方法
instanceof(); 用于确定一个 PHP 变量是否属于某一类 class 的实例
魔术方法:
__call 魔术方法,重载(动态创建类属性和方法).当调用,未定义或不可见的方法时,被调用.
__callStatic 魔术方法,在静态类中调用一个不可访问的类时,该魔术方法会被调用.
__clone 魔术方法,进行克隆时调用.用以调整对象的克隆行为.
__construct 魔术方法,构造函数,构建对象时被调用.
__invoke 魔术方法,当以调用函数的方式调用一个对象时(包含回调),会被自动调用.
__destruct 魔术方法,明确销毁对象, 或脚本结束是被调用.
__get 魔术方法,读取不可访问或不存在的属性时被调用.
__set 魔术方法,当给不可访问或不存在的属性赋值时调用.
__isset 魔术方法,对不可访问或不存在的属性使用isset()或empty()时被调用
__unset 魔术方法,对不可访问或不存在的属性进行unset时调用.
__sleep 魔术方法,当使用serialize序列化时被调用,当你不需要保存大对象的所有数据时很有用
__wakeup 魔术方法,当使用unserialize反序列化时被调用,可用于对象的初始化操作.例如重新建立数据库连接,或执行其它初始化操作。
__debuginfo 魔术方法,当调用var_dump();打印对象时调用.
__toString 魔术方法,方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。经常在继承Exception类的时候会封装这个方法.
访问控制及调用
public 访问控制 公开的(方法/属性),可以在任何地方访问.
protected 访问控制 受保护的(方法/属性),只能在自身,子类,父类中访问.
private 访问控制 私有的(方法/属性),只能在被定义类自身使用.如果构造函数定义成了私有方法则不允许直接实例化对象了,这时候一般通过静态方法进行实例化
static 定义静态(方法/属性);
静态成员持有者是类不是对象,所以类的多个实例共享同一个静态属性的,在一个实例中修改静态属性会影响到另一个实例中的静态属性
这个就是重点了,好好理解下,单列模式也是利用这个特性。
final 关键字, 禁止该方法被子类覆盖重写,或类被继承.
第四种访问控制 一般来说都认为PHP是三种访问控制,今天听CTO说在定义静态属性时,不写访问控制就是第四种,大概意思是,只能在同目录下访问什么的
parent:: 调用父类(方法/属性/变量 )
static:: 和self用法差不多,引用的是全部静态作用域,子类的静态元素会覆盖父类
self:: 调用自身静态(方法/变量/属性)(单纯该关键字为指向当前类本身)
this 指向对象实例可以使用$this->调用常规(方法/属性)
上面3个的差异性:
这三个特殊的关键字是用于在类定义的内部对其属性或方法进行访问的
static::
作用域太..所以我从来都不用.
static 关键字,这里作为作用域引用。
类似于parent, self等关键字。与parent和self不同的是,
parent 引用的是父类作用域,self引用的是当前类的作用域,
而static引用的是全部静态作用域,子类会覆盖父类.
self::
指向定义了当前被调用方法的类(就是该哪里还是哪里),
在静态方法中想要返回自身类,需要return new self();或者return new 类名.
$this
指向对象实例,普通方法中返回自身类可以使用return $this或类名.
普通方法中返回自身类可以使用return $this或类名.
抽象类: abstract关键字
abstract使用:
声明一个抽象类或声明一个抽象方法,抽象类不可被实例化,只能通过继承来实例化.
用abstract修饰的类表示这个方法是一个抽象方法,抽象方法,只有方法的声明部分,没有方法体.
抽象方法没有 {} ,而采用 ; 结束.
一个类中,只要有一个抽象方法,这个类必须被声明为抽象类.
抽象方法在子类中必须被重写(所以并不常用).
抽象类在被继承后,其中的抽象方法不能被重写
继承的派生类当中要把所有抽象方法重载才能实例化
抽象类继承抽象类:
抽象类继承另外一个抽象类时,不用重写其中的抽象方法
抽象类中,不能重写抽象父类的抽象方法
这样的用法,可以理解为对抽象类的扩展
对象接口: interface关键字
接口声明:
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容.
接口是通过 interface关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的.
接口中定义的所有方法都必须是公有,这是接口的特性,
接口可以extends继承接口,一个接口也可以继承多个接口.使用,分割.
接口可定义常量和静态常量, 并且可以在外部直接使用和继承.
接口实现:
要实现一个接口,使用 implements继承接口 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。
类可以实现多个接口,用逗号来分隔多个接口的名称。
类可以extends继承类,同时再implements继承接口.
性状类: trait
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。
Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method
通过在类中使用use 关键字,声明要组合的Trait名称,具体的Trait的声明使用Trait关键词,Trait不能实例化
一个类可以组合多个Trait,通过逗号相隔
可变参数也叫不定参数:
//可变参数$num是一个索引数组,可以传入任意多个参数
function sum(int ...$num) {
return array_sum($num);
}
//上面那种上和原来我们这样用的方式结果是一样的,不过下面这这个没有类型约束
function sum() {
return array_sum(func_get_args());
}
类型约束
强制模式(默认):体现在类型转换上
严格模式 模式声明:declare(strict_types=1);
默认情况值为0,值为1代表为严格校验的模式
declare(strict_types=1);
类型约束:
函数的参数,可以指定必须为对象,(在函数名中指定类的名字),接口,数组或者callback,不过如果使用null作为参数的默认值,
那么在调用函数时,依然可以使用null作为参数.(类型约束不包括,Int或string等标量类型,Traits 也不允许);
function f(类名 $param) 要求参数只能是某类的对象
function f(interface接口名 $param) 要求参数只能使用实现该接口的对象
function f(array $param) 要求参数只能使用数组
function f(callable $param); 要求参数只能为一个回调函数
php7标量类型声明:
现在可以使用下列类型参数(无论用强制模式还是严格模式):
字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。
它们扩充了PHP5中引入的其他类型:类名,接口,数组和 回调类型。
如:
//这里一旦被标识,传入的参数必须是整型,否则报一个致命错误:TypeError
function sum(int $leftNum, int $rightNum){
return $leftNum+$rightNum;
}
php7返回类型声明:
现在可以使用下列类型参数(强制模式下我也许爱, 严格模式下时生效,declare(strict_types=1);时生效,不写默认为0):
int,float,bool,string,interfaces,array,callable
如:
//这个函数一旦返回的不是整型,即产生一个Fatal error:TypeError
function sum($leftNum,$rightNum):int
{
return $leftNum+$rightNum;
}