主要是记录一些不会常用到的东西, 因此可能看起来很无聊,碰到什么就加点什么,所以会一直更新下去。
...语法糖
...是php语法糖的一种,很少用,感觉有点鸡肋,他的作用是这样的,在我们给函数传递参数的时候,可以将传递的参数展开,或者收集到一个数组变量中。还是代码好说明问题。
-
声明函数的时候使用,是个索引数组,要是关联就更棒棒了
function test(...$names){
echo '一共有'. count($names) . '个名字' . "\n";
foreach ($names as $k=>$name){
echo '第' . $k . '个名字是' . $name ."\n";
}
}
test('zhangsan', 'lisi', 'wangwu')
- 使用函数的时候使用
function test($name, $age){
echo 'name is ' . $name, ' age is ' . $age;
}
test(...['zhangsan', 32]);
register_shutdown_function()
在php脚本结束时,回调注册的函数,执行顺序是按注册顺序来的。
register_shutdown_function($callback, $parameters,...)
function test($name, $age){
return $name . $age;
}
register_shutdown_function('test', 'zhangsan', 32);
json_encode()
不知道为什么会出现这种情况,难道是php默认把字符串0 转换成了数字0, 然后就默认是数组了???r
var_dump(json_encode(['1'=>'22', '0'=> '12']));
// {"1":"22","0":"12"}
var_dump(json_encode(['0'=>'22', '1'=> '12']));
// ["22","12"]
echo json_encode([1,2,3], JSON_FORCE_OBJECT);
// {"0":1,"1":2,"2":3}
var_dump(json_encode(['0'=>'22', '2'=> '12']));
// {"0":"22","2":"12"}
var_dump(json_encode(['1'=>'22', '2'=> '12']));
// {"1":"22","2":"12"}
var_dump(json_encode([1=>'22', 2=> '12']));
// {"1":"22","2":"12"}
貌似是这样, 只要是以0开头并且是连续的索引数组,结果都是数组,除此之外就是json对象
闭包对象的 bindTo()
虽然为我们访问对象提供了方便,但是访问外部变量还是需要使用
use, 具体不清楚怎样使用才能更好
class Person{
private $name = 'page';
function testf(){
$st = new Student();
$colus = function (){
echo $this->name . PHP_EOL;
};
//将student对象绑定到闭包的上下文中
$st_closure = $colus->bindTo($st);
//将当前对象绑定到闭包上下文中
$self = $colus->bindTo($this);
$self(); // page
$st_closure(); // student
}
}
class Student{
public $name = 'student';
}
$tes = new Person();
$tes->testf();
spl php的标准库
在php的标准库中有一些非常有意思的东西,比如,常用的数据结构类的, 队列、双向链表、栈结构, 等等,还有一些预定义的接口, 迭代器什么的
-
队列
SplQueue通过查看手册我们可以看到, 队列结构的实现是继承了双向链表,然后实现了
Iterator、ArrayAccess、Countable接口,当然它也就具有了双向列表的所有方法, 我们可以根据isEmpty()方法的返回值,来断定一个队列是否为空$queue = new SplQueue(); $queue->enqueue('item1'); //入队列 $queue->enqueue('item2'); echo $queue->dequeue(); // 出队列 echo $queue->dequeue(); var_dump($queue->isEmpty()); // true
其他的一些结构还是看手册比较详细。。
生成器 generator
目前我只感受到一种使用生成器的优势,就是在读取超大文件的时候。设想有这样一个场景吗,我们要对一个文件的数据进行过滤,肯定有些人会尝试使用
file_get_contents()这个函数, 但是如果这个文件比较大,比如几个G呢,这时全部读入,无疑是不现实的,这时我们就可以使用生成器来完成。ps: 其实这个也是有另外的解决方式,这里只是为了说明生成器的一种使用场景
**感觉对生成器的理解还是不深,后面再找找资料**
// 使用生成器, 返回的生成器对象
function readText(){
$fp = fopen('./ff.pdf', 'rb');
while ( !feof($fp) ) {
yield fgets($fp);
}
}
// 由于是默认的php_memory_limit, 直接就超出内存了,不可取
function arrread(){
$da = '';
$fp = fopen('./ff.pdf', 'rb');
while ( !feof($fp) ) {
$da .= fgets($fp);
}
}
//使用 readText(),返回的生成器对象,顺利完成
foreach (readText() as $item) {
echo $item, '<br>';
}
echo xdebug_memory_usage();
do{}while(condition); 特殊用法
$a = 1;
$b = 3;
do{
if ($a > 1){
echo 'a';
break;
}
if ($b >3){
echo 'b';
break;
}
echo 'end';
}while(false);
// 由于两个if条件都不满足, 所以执行了echo 'end'; 这从某种方面实现了goto的作用
定义一个函数并立即执行
之前看golang的时候, golang 有这么一种语法
package main
import . "fmt"
func main(){
func (){
Printf("%s\n", "定义并立即执行")
}()
}
里面的闭包函数可以直接定义并且执行一次,那么作为世界上最好的语言, PHP能不能呢, 答案是可以的。
(function(){
echo '定义并立即执行' . PHP_EOL;
})()
function外不加小括号会报语法错误, 看起来没有go那么简洁。 或许可以用来定义生成器, 这样就不用单独的声明函数了, 一个不错的选择。
foreach( (function(){
for ($i = 0; $i < 10; ++$i){
yield $i;
}
})() as $num) {
echo $num . PHP_EOL;
}
其实js也是可以的, 原理就是定义一个闭包函数, 并立即执行。
变换时间单位 秒变成时分秒
这里可以巧用php类DateInterval, DateTime来实现
function invertTime($interval_spec, $format="%Y年 %m月 %d日 %H时 %i分 %S秒"){
return date_diff(new DateTime(), (new DateTime())->add(new DateInterval($interval_spec)))->format($format);
}
echo invertTime('P1YT12301S');