5.5

1. yield

参考链接: https://www.jianshu.com/p/103cbf359971
当函数需要返回一个迭代器的时候, 逐个返回值;生成器yield关键字不是返回值,他的专业术语叫产出值,只是生成一个值
未使用yield, 内存使用输出如下
1.15 MB
9.15 MB
17.15 MB
33.15 MB

function getValues() {
    $valuesArray = [];
    // 获取初始内存使用量
    echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
    for ($i = 1; $i < 800000; $i++) {
        $valuesArray[] = $i;
        // 为了让我们能进行分析,所以我们测量一下内存使用量
        if (($i % 200000) == 0) {
            // 来 MB 为单位获取内存使用量
            echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB'. PHP_EOL;
        }
    }
    return $valuesArray;
}
$myValues = getValues(); // 一旦我们调用函数将会在这里创建数组
foreach ($myValues as $value) {}

使用yield, 内存使用输出如下
1.15 MB
1.15 MB
1.15 MB
1.15 MB

function getValues()
{
    // 获取内存使用数据
    echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
    for ($i = 1; $i < 800000; $i++) {
        yield $i;
        // 做性能分析,因此可测量内存使用率
        if (($i % 200000) == 0) {
            // 内存使用以 MB 为单位
            echo round(memory_get_usage() / 1024 / 1024, 2) . ' MB' . PHP_EOL;
        }
    }
}

$myValues = getValues(); // 在循环之前都不会有动作
foreach ($myValues as $value) {} // 开始生成数据

执行过程

  1. 首先调用 createRange 函数,传入参数5,但是 for 值执行了一次然后停止了,并且告诉 foreach 第一次循环可以用的值。
  2. foreach 开始对 $result 循环,进来首先 sleep(1) ,然后开始使用 for 给的一个值执行输出。
  3. foreach 准备第二次循环,开始第二次循环之前,它向 for 循环又请求了一次。
  4. for 循环于是又执行了一次,将生成的时间戳告诉 foreach
  5. foreach 拿到第二个值,并且输出。由于 foreach 中 sleep(1) ,所以, for 循环延迟了1秒生成当前时间
function createRange($number)
{
    for ($i = 0; $i < $number; $i++) {
        yield time();
    }
}

$result = createRange(3); // 这里调用上面我们创建的函数
foreach ($result as $value) {
    sleep(1);
    echo $value, PHP_EOL;
}
/*
1564559537
1564559538
1564559539
*/

读取5G大文件实例

header('content-type:text/html;charset=utf-8');
function readTxt()
{
    $handle = fopen('../txt/t2.txt', 'rb');

    while (feof($handle) === false) {
        yield fgets($handle);
    }

    fclose($handle);
}

foreach (readTxt() as $key => $value) {
    echo $value . PHP_EOL;
}

2. list()

用于foreach 可以用 list() 在 foreach 中解析嵌套的数组

$array = [
    [1, 2, 3],
    [4, 5, 6],
];
foreach ($array as list($a, $b, $c))
    echo "{$a} {$b} {$c}\n";
/*
1 2 3
4 5 6
 */

3. array和string变量可以直接取值

echo [1, 2, 3][0], PHP_EOL; // 1
echo 'PHP'[0], PHP_EOL; // p

4. empty()支持任意表达式

function always_false()
{
    return false;
}

if (empty(always_false())) echo '1';
if (empty(true)) echo '2';
if (empty(1 + 1)) echo '3';
if (empty(1 > 0)) echo '4';
// This will be printed.

5. try-catch结构新增finally块

try {
    throw new Exception('1');
} catch (Exception $e) {
    echo $e->getMessage(), PHP_EOL; // 1
} finally { // 只要执行了try或者catch, 就一定会执行finally
    echo '2', PHP_EOL; // 2
}

6. 可用MyClass::class取到类的完整限定名(包括命名空间);

namespace app\api;
class A
{
    public function get()
    {
        echo self::class; // app\api\A
    }
}

echo A::class; // app\api\A

细节修改
不推荐使用 mysql 函数,推荐使用 PDO 或 MySQLi;