php 不常用的东西

主要是记录一些不会常用到的东西, 因此可能看起来很无聊,碰到什么就加点什么,所以会一直更新下去。

...语法糖

... 是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的标准库中有一些非常有意思的东西,比如,常用的数据结构类的, 队列、双向链表、栈结构, 等等,还有一些预定义的接口, 迭代器什么的

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');