學習PHP中YAML操作擴充套件的使用

硬核專案經理發表於2021-11-23

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/

相關文章