学习PHP中YAML操作扩展的使用

YAML 这个东西,说实话,自己用得并不多。在学习自动化测试相关的内容时候,接触过使用这种配置文件来配置 Travis CI 的持续集成操作,当然,当时也是以学习性质为主的。虽说接触得不多,但也知道确实这种配置格式的写法基本上已经成为了现在的主流。所以关于具体的 YAML 相关的内容在这里就不多做解释了,还不是太了解的同学可以自行查阅一些相关的文档。

我们今天来学习的主要是一个 PHP 中用来解析和转换 YAML 格式的扩展,安装过程并没有什么特别的可以说明的地方,就和其它的扩展一样进行安装即可。不过这个扩展需要一个 libyaml-devel ,在 CentOS 中直接通过 yum 或者 dnf 是无法安装的,我们可以在文末的链接中找到下载地址。

将 PHP 数据转换成 YAML

对于将 PHP 的数据转换成 YAML 来说,其实就和 JSON 相关的操作差不多,将数组转换成 YAML 格式的字符串。

$addr = array(
    "given" => "Chris",
    "family"=> "Dumars",
    "address"=> array(
        "lines"=> "458 Walkman Dr.
        Suite #292",
        "city"=> "Royal Oak",
        "state"=> "MI",
        "postal"=> 48046,
      ),
  );
$invoice = array (
    "invoice"=> 34843,
    "date"=> 980208000,
    "bill-to"=> $addr,
    "ship-to"=> $addr,
    "product"=> array(
        array(
            "sku"=> "BL394D",
            "quantity"=> 4,
            "description"=> "篮球",
            "price"=> 450,
          ),
        array(
            "sku"=> "BL4438H",
            "quantity"=> 1,
            "description"=> "Super Hoop",
            "price"=> 2392,
          ),
      ),
    "tax"=> 251.42,
    "total"=> 4443.52,
    "comments"=> "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.",
  );

$yamlString = yaml_emit($invoice);
var_dump($yamlString);
// string(624) "---
// invoice: 34843
// date: 980208000
// bill-to:
//   given: Chris
//   family: Dumars
//   address:
//     lines: |-
//       458 Walkman Dr.
//               Suite #292
//     city: Royal Oak
//     state: MI
//     postal: 48046
// ship-to:
//   given: Chris
//   family: Dumars
//   address:
//     lines: |-
//       458 Walkman Dr.
//               Suite #292
//     city: Royal Oak
//     state: MI
//     postal: 48046
// product:
// - sku: BL394D
//   quantity: 4
//   description: "\u7BEE\u7403"
//   price: 450
// - sku: BL4438H
//   quantity: 1
//   description: Super Hoop
//   price: 2392
// tax: 251.42
// total: 4443.52
// comments: Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.
// ...
// "

可以看到 yaml_emit() 函数转换的结果是非常标准的 YAML 格式。开头有 --- ,结尾有 ... 。但你会发现有很多教程或者框架中的 .yml 文件中是没有这些符号的,从官方文档中得知这些符号是建议写得,而我们的扩展则是非常地遵守建议,也就是转换的结果非常地标准。

此外,在测试代码中我们加入了中文的内容。可以看到直接转换的时候中文被编码了。就像 JSON 操作一样,在 YAML 这个扩展的函数中,我们也可以指定编码格式让中文原样显示。

var_dump(yaml_emit($invoice, YAML_UTF8_ENCODING));
// string(616) "---
// ………………
//   description: 篮球
// ………………
// ...
// "

将 YAML 转为 PHP 数组

没错,也是类似于 JSON 操作的,将 YAML 格式的字符串格式内容反转回 PHP 数据内容。

var_dump(yaml_parse($yamlString));
// array(8) {
//     ["invoice"]=>
//     int(34843)
//     ["date"]=>
//     int(980208000)
//     ["bill-to"]=>
//     array(3) {
//       ["given"]=>
//       string(5) "Chris"
//       ["family"]=>
//       string(6) "Dumars"
// ………………
// ………………

同样非常简单地一个 yaml_parse() 函数。除了直接操作字符串之外,我们还可以直接提取文件内容来进行转换,包括上面的 yaml_emit() 函数也是有类似的直接将结果写入到文件中的。

var_dump(yaml_parse_file('styleci.yml'));
// array(3) {
//     ["php"]=>
//     array(3) {
//       ["preset"]=>
//       string(7) "laravel"
//       ["disabled"]=>
//       array(1) {
//         [0]=>
//         string(10) "unused_use"
//       }
//       ["finder"]=>
//       array(1) {
//         ["not-name"]=>
//         array(2) {
//           [0]=>
//           string(9) "index.php"
//           [1]=>
//           string(10) "server.php"
//         }
//       }
//     }
//     ["js"]=>
//     array(1) {
//       ["finder"]=>
//       array(1) {
//         ["not-name"]=>
//         array(1) {
//           [0]=>
//           string(14) "webpack.mix.js"
//         }
//       }
//     }
//     ["css"]=>
//     bool(true)
//   }

我们测试的这个文件就是 Laravel 中自带的那个 .styleci.yml 文件。在 Laravel 框架中并没有要求我们安装这个 YAML 扩展,似乎在框架中本身就有解决读取转换这种 YAML 格式的工具,这个我们最后再说。和 yaml_parse_file() 类似地,yaml_emit_file() 是直接将 PHP 数据转换为 YAML 格式之后直接写入到一个文件中,大家可以自己测试一下。

回调函数处理标签

不管是 yaml_emit() 还是 yaml_parse() 都是支持一个回调参数操作的。我们先来看看例子。

// php:
//   preset: !laravel laravel
//   disabled:
// ………………
// ………………
function callback($value){
    return str_replace('laravel', 'new version laravel8', $value);
}
$ndocs = 0;
var_dump(yaml_parse_file('styleci.yml', 0, $ndocs, ['!laravel'=>'callback']));
// array(3) {
//     ["php"]=>
//     array(3) {
//       ["preset"]=>
//       string(20) "new version laravel8"
//       ["disabled"]=>
//       array(1) {
// ……………………
// ……………………

这是什么意思呢?!laravel 这种写法可以看做是 YAML 中的一种标签格式的写法。而这个回调的作用就是在遇到类似的这类标签的时候,使用什么回调函数来进行处理。比如我们的原文档中的 !laravel 后面的内容是 laravel 。在回调函数中我们将内容替换成了 new version laravel8 ,于是,最后输出的结果就是 preset 字段的内容变成了 new version laravel8 。当然,更加详细的内容以及更多地语法还是需要我们深入地了解 YAML 格式的语法才能够更加清楚,所以这里也就不多说了,毕竟自己也接触得不多。

总结

对于这个扩展的内容不多,而且即使是真实的业务环境中需要操作 YAML 格式的配置文件的话估计我也不会用它。为什么呢?当然是因为 Composer 里面已经有很多处理 YAML 的组件可以供我们使用啦。完全不需要通过扩展编译安装的方式来对服务器上的 PHP 环境进行改变。如果是自己使用的话,在 packagist.org 中能找到很多组件,而如果是使用 Laravel 的话,它的底层使用的其实是 symfony 框架中 yaml 处理组件。直接使用 composer require symfony/yaml 就可以为自己的小项目添加这个组件咯。具体内容可以参考这个文档:

https://symfony.com/doc/current/components/yaml.html

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/2021/01/source/10.学习PHP中YAML操作扩展的使用.php

参考文档:

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

http://www.rpmfind.net/linux/rpm2html/search.php?query=libyaml-devel(x86-64))

http://bd808.com/pecl-file_formats-yaml/

你可能感兴趣的