PHP中的一些杂项函数学习

今天来学习的这些杂项函数在官方文档中都是放在一个杂项扩展中的,其实这些函数都并不是什么什么特别的扩展,也不需要安装什么东西就可以使用,它们就是一些简单的功能函数而已。当然,其中不少内容也是我们经常会使用的,这里就带大家一起再学习学习。

常量操作

常量的操作相信对于我们日常使用 PHP 开发的小伙伴来说绝对不会陌生。不管是使用框架还是自己写代码,经常会使用到常量相关的内容。

define("A", "Test A");
var_dump(A); // string(6) "Test A"
var_dump(B); // Warning: Use of undefined constant B - assumed 'B'

var_dump(constant('A')); // string(6) "Test A"
var_dump(constant('B')); // NULL
// PHP Warning:  Use of undefined constant B - assumed 'B'   

var_dump(defined('A')); // bool(true)
var_dump(defined('B')); // bool(false)

简单地定义常量就是使用 define() 这个函数,它有两个参数,第一个参数是常量的名称,第二个参数就是常量的值。这里需要注意的是,常量的值只能是标量类型,也就是数字、字符串这类的内容,不能是变量或者对象类型,因为这类型的内容都有随时改变的可能。

直接使用常量名就可以打印出常量的内容,当然,我们也可以使用 constant() 这个函数来获取常量的内容,它可以接收字符串类型的参数的常量名。

defined() 这个函数是用于判断指定的常量是否存在,它只比 define() 函数多了一个字母 d ,在使用的时候要小心,不要在定义常量的时候多写了这个 d 哦。

对于接口和类来说,也可以在它们的内部使用 const 关键字来定义内部常量。

interface A1{
    const TEST = 'Test A1';
}

class A2{
    const TEST = 'Test A2';
}

var_dump(constant('A1::TEST')); // string(7) "Test A1"
var_dump(constant('A2::TEST')); // string(7) "Test A2"

var_dump(defined('A1::TEST')); // bool(true)
var_dump(defined('A2::TEST')); // bool(true)

内部常量是有作用域范围的,它们只在类的内部生效。而且在默认情况下,这些常量直接就是静态类型的,不需要我们再单独添加 static 关键字。

代码高亮及文件格式相关

我们可以使用一个函数,来让代码实现高亮的效果。其实也就是给指定的代码内容增加了 code 以及一些格式标签。

var_dump(highlight_string('', true));
// string(195) "
// <?php phpinfo(); ?>
// 
// "

highlight_string() 的第二个参数是指定返回的类型,如果我们不给这个参数的话,它的默认值是 false ,这样调用 highlight_string() 时就会直接输出而不是将内容作为返回值返回。也就是说,像 phpinfo() 这类函数一样,它会直接将结果打印出来。

另外,我们也可以直接对一个文件里面的内容进行高亮操作。

var_dump(highlight_file('1.PHP中的一些杂项函数学习.php', true));
// string(10610) "
// <?php


define
("A""Test A");
var_dump(A); // string(6) "Test A"
var_dump(B // <?php


define
("A""Test A");
var_dump(A); // string(6) "Test A"
var_dump(Bvar_dump(php_strip_whitespace("1.PHP中的一些杂项函数学习.php")); // string(570) "

时间操作函数

在杂项函数中,也有一些时间相关的操作函数,比如系统运行的时间。

echo hrtime(true), PHP_EOL; // 2636292334692
print_r(hrtime());
// Array
// (
//     [0] => 2636
//     [1] => 292338001
// )

在之前的文章中我们其实有讲过这个 hrtime() 函数的作用。它返回的是当前操作系统开机到现在经过的时间,比如我的电脑是早上开机的,从开机到现在只经过了 2636 秒。它返回的是纳秒级别的,如果不加那个布尔类型为 true 的参数的话,它就会以数组的形式返回,0 下标的是秒数,1 下标的是纳秒数。而如果加了 true 参数的话,它就会直接以数字格式返回整体的秒加上纳秒数。

另外一些时间相关的函数就是暂停程序执行的一些函数,比如我们经常会用到的 sleep() 函数。

$time = microtime(true);
echo $time, PHP_EOL; // 1609723496.283
sleep(1);
echo microtime(true) - $time, PHP_EOL; // 1.0041399002075
usleep(2000);
echo microtime(true) - $time, PHP_EOL; // 1.0062718391418
time_nanosleep(2, 100000);
echo microtime(true) - $time, PHP_EOL; // 3.0067868232727
time_sleep_until(time()+3); 
echo microtime(true) - $time, PHP_EOL; // 5.7171077728271

sleep() 是以秒为间隔暂停程序的执行。而其它的两个函数 usleep() 则是以微秒, time_nanosleep() 是以纳秒来进行暂停的。最后一个 time_sleep_until() 所需要的参数则是暂停到指定的时间,比如这里我们指定在三秒后暂停,它需要的参数就是 time() + 3 这个时间戳。当然,我们在日常开发中最常用的还是 sleep() 和 usleep() 。这里大家可以当做扩充一下知识点,我们 PHP 是可以实现纳秒级的暂停的。

生成唯一ID

生成唯一ID这个函数相信不少同学也经常使用,就是那个 uniqid() 函数。不过它的原理和参数你了解嘛?

var_dump(uniqid()); // string(13) "5ff270b0014b4"

var_dump(uniqid('pre_')); // string(17) "pre_5ff270b0014d7"

var_dump(uniqid('pre_', true)); // string(27) "pre_5ff270b0014df3.11521937"

uniqid() 是基于当前时间微秒数来生成唯一ID的,也就说它并不能完全地保证生成的这个 ID 是唯一的。在超大并发的前提下,很有可能在一微秒内就有多个请求到达,所以也是有可能生成多个重复的 ID 的。

在这种情况,我们可以通过它的参数来让生成的 ID 更具有的唯一性。第一个参数是可以指定生成 ID 的前缀,对于不同的业务或者不同的负载均衡之后的处理机器我们就可以使用不同的前缀来进行区分。第二个参数则是在返回的字符串结尾增加额外的熵,它可以进一步提升唯一性的可能性。

其它函数

除了上面介绍的那些比较常见和常用的函数外,杂项函数中还包含其它一些不是那么常用的内容。

系统负载

我们可以通过一个函数 sys_getloadavg() 来查看当前操作系统的负载情况,返回的结果数组对应的就是 Linux 系统中的 1m 、5m 和 15m 的负载情况。

var_dump(sys_getloadavg());
// array(3) {
//     [0]=>
//     float(2.98828125)
//     [1]=>
//     float(2.4775390625)
//     [2]=>
//     float(2.341796875)
//   }

执行代码

eval() 这个函数和 JavaScript 中的 eval() 不管名称还是作用都是一样的,可以解析并运行一个字符串中的 PHP 代码。不过需要注意的是,它也是属于危险函数哦。要运行的字符串一定是我们自己可控的内容,千万不要运行用户能够上传的内容哦。

eval("echo '123', PHP_EOL;"); // 123

退出中断程序

exit;
die;
exit(0);
exit("End"); // End

exit() 和 die() 不用过多介绍了,它们两个的作用是一样的,可以将 die() 看成是 exit() 的别名。如果在没有参数的情况下,可以省略不写后面的括号。而参数的作用是在中断程序运行后进行输出。如果参数是字符串,则直接输出字符串的内容,如果参数是数字,则相当于是返回程序的运行状态码,和 Linux 中的状态码是一样的概念。

浏览器信息

当我们使用浏览器访问的时候,可以通过 get_browser() 函数来获得浏览器的一些信息。

var_dump(get_browser(null, true));
// array(15) {
//     ["browser_name_regex"]=>
//     string(108) "~^mozilla/5\.0 \(.*mac os x 10.15.*\) applewebkit.* \(.*khtml.*like.*gecko.*\) .*version/14\.0.* safari/.*$~"
//     ["browser_name_pattern"]=>
//     string(88) "Mozilla/5.0 (*Mac OS X 10?15*) applewebkit* (*khtml*like*gecko*) *Version/14.0* Safari/*"
//     ["parent"]=>
//     string(11) "Safari 14.0"
//     ["platform"]=>
//     string(5) "macOS"
//     ["comment"]=>
//     string(11) "Safari 14.0"
//     ["browser"]=>
//     string(6) "Safari"
//     ["browser_maker"]=>
//     string(9) "Apple Inc"
//     ["version"]=>
//     string(4) "14.0"
//     ["majorver"]=>
//     string(2) "14"
//     ["device_type"]=>
//     string(7) "Desktop"
//     ["device_pointing_method"]=>
//     string(5) "mouse"
//     ["minorver"]=>
//     string(1) "0"
//     ["ismobiledevice"]=>
//     string(0) ""
//     ["istablet"]=>
//     string(0) ""
//     ["crawler"]=>
//     string(0) ""
//   }

需要注意的是,这个函数需要一个 browscap.ini 文件的支持,可以从 http://browscap.org 这里下载到 browscap.ini 文件,并在 php.ini 文件中指定 browscap 的路径到你下载的这个 browscap.ini 文件。这个函数非常少见,大家了解一下即可。

连接信息

最后就是关于 PHP 脚本的连接信息的查看,也就是脚本与客户端的连接信息的查看。

ignore_user_abort(true);
while(1){
    echo " ";
    if (connection_status()!=0){
        ob_start();
        var_dump(connection_aborted());
        $v = ob_get_contents();
        ob_end_flush();
        file_put_contents("1.txt", date("Y-m-d H:i:s") . " Connection aborted! " . $v . PHP_EOL, FILE_APPEND);
        exit;
    }
}

// 1.txt
// 2021-01-04 08:56:22 Connection aborted! int(1)

ignore_user_abort() 函数用于设置客户端断开连接时是否中断脚本的执行,当我们访问这个测试页面后,马上在浏览器上关闭它,就会触发这个函数。

下面的无限循环代码是用于监控当前连接的状态,使用的是 connection_status() 这个函数,当它的值为 0 时,也就是 CONNECTION_NORMAL 这个状态是属于正常连接的状态,而当它不为 0 的时候,我们就记录到一个日志文件中。connection_aborted() 是判断连接是否中断的函数,这是一个直接输出流的函数,我们需要通过 输入输出流 来捕获它的内容。

最后,当浏览器关闭的时候,连接相关的内容就记录到了 1.txt 这个文件中。我们可以查看这个文件里面的信息。

总结

怎么样,今天的内容虽然是 PHP 文档中的杂项扩展,而且内容也确实很杂,但它们有不少内容确实是我们经常使用的。掌握好它们,扩宽自己的眼界,总有一天这些内容会为你带来福报,加油吧,打工人。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/01/source/1.PHP中的一些杂项函数学习.php

参考文档:

https://www.php.net/manual/zh/book.misc.php

==============

各自媒体平台均可关注【硬核项目经理】