iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 3
0
自我挑戰組

花式PHP系列 第 3

關聯陣列、花式函式宣告與呼叫

/images/emoticon/emoticon30.gif

PHP 的 Array 比較特別的地方是,
它其實可以是其他語言的 MAP,也可以是 List、Hash Table、Dictionary!

在 PHP 中,通常把我們能在 Array 中使用 String key 與一組值對應的行為稱做 Associative Array。

Array 與 JSON

在大多數時候,PHP 的 Associative array都能作為一種很優秀的 JSON 資料呈現、撰寫的方式~
比如下面的這段描述歌曲資料的 JSON 就能透過 Assoc array 的方式撰寫:

{
  "status": "OK",
  "message": "it's Ok I said",
  "data": [
    {
      "id": "77390b1c949ec9f032d8cee769a2e04f",
      "name": "五里霧中",
      "artist": "康士坦的變化球",
      "album": "擱淺的人"
    },
    {
      "id": "299cddc93f2c7b2a7963e4b3be8db4f0",
      "name": "Pensées",
      "artist": "Mashk, Soul Button",
      "album": "Pathos"
    },
    {
      "id": "24b292eb83ff904e2efbb6494448f646",
      "name": "Казался странным",
      "artist": "Елена Темникова",
      "album": "TEMNIKOVA II"
    }
  ]
}

再來是對應的 PHP 語法:
(如果單純把 PHP 的 Array 當成其他語言的 List 來用就很可惜了。)

<?php

$data = [
    'status' => 'OK',
    'message' => 'it\'s Ok I said',
    'data' => [
        [
            'id' => '77390b1c949ec9f032d8cee769a2e04f',
            'name' => '五里霧中',
            'artist' => '康士坦的變化球',
            'album' => '擱淺的人',
        ],
        [
            'id' => '299cddc93f2c7b2a7963e4b3be8db4f0',
            'name' => 'Pensées',
            'artist' => 'Mashk, Soul Button',
            'album' => 'Pathos',
        ],
        [
            'id' => '24b292eb83ff904e2efbb6494448f646',
            'name' => 'Казался странным',
            'artist' => 'Елена Темникова',
            'album' => 'TEMNIKOVA II',
        ],
    ],
];

echo(json_encode($data));

使用 Javascript 接收 JSON

Assoc Array 中自訂 String key 的地方其實就是在提供一個 Object
而不特別指定 String key 的地方就是在提供一個單純的 Array

使用 PHP 接收 JSON

注意 json_decode() 的第二個參數可以指定要把 Object 的部分轉成 stdClass 或是 Assoc Array。
這一點影響到你後續如何在 PHP 中查找你收到的資料。

Array 與 Function Call

使用 ... 宣告可變參數函數

可變參數函數?

『...可變參數函數是指一個函數擁有不定引數,即是它接受一個可變數目的參數。...』
~ 維基百科

這段話的意思是,
PHP 接受我們宣告一個能接受不恆等數量參數的 Function!

這麼做的好處在哪呢?

比如當我們不確定這個 function 後續會如何擴充它需要哪些變數,
就可以使用 ... 來宣告這個 function 的參數。

舉例

讓我們延續上一章的資料來舉例,
底下是一個能計算歌曲資料(用 Object 來計算)其 md5 的 function :

在這個章節我會使用到上個段落的 $data
但這章節的 $data 是透過 json_decode($data, FALSE) 輸出的

<?php

function calculateMd5ForObject(stdClass $row): String
{
    /*
     * 這邊我透過把 object 的資訊,
     * 用 debug 時常用的 var_export 轉成 string,再拿 string 去計算 md5。
     * 
     * @see http://php.net/manual/en/function.var-export.php
     */
    return md5(var_export($row, TRUE));
}

$data = json_decode(json_encode($data), FALSE);

echo calculateMd5ForObject($data->data[0]);

上面這個 Function 被設計成只能一次計算一個 Object 的 md5,
如果我們想得到數筆資料的 md5 就只能用 foreacharray_map 依序執行。

但只要改寫一下 function 就能簡化掉使用 foreach 的麻煩:

改寫 -1

<?php

function calculateMd5ForObjects(stdClass $rowA, stdClass $rowB, stdClass $rowC): array
{
    $rows = [$rowA, $rowB, $rowC];
    
    /*
     * @see http://php.net/manual/en/function.array-map.php
     */
    return array_map(function ($row) {
        return md5(var_export($row, TRUE));
    }, $rows);
}

$data = json_decode(json_encode($data), FALSE);

/*
 * 使用 print_r 印出陣列的資料
 * @see http://php.net/manual/en/function.print-r.php
 */
print_r(calculateMd5ForObjects(
    $data->data[0],
    $data->data[1],
    $data->data[2]
));

上面這樣子寫,我們就能一次接受三筆資料了呢~
但是固定就是三筆,不能再多了!
/images/emoticon/emoticon03.gif

不過有 ... 的幫助的話,我們可以做的更好的:

改寫-2

<?php

function calculateMd5ForObjects(stdClass ...$rows): array
{
    /*
     * @see http://php.net/manual/en/function.array-map.php
     */
    return array_map(
        function ($row) {
            return md5(var_export($row, TRUE));
        },
        $rows
    );
}

$data = json_decode(json_encode($data), FALSE);

print_r(calculateMd5ForObjects(
    $data->data[0],
    $data->data[1]
));

/images/emoticon/emoticon35.gif
這樣子484看起來舒服很多呢~

而且現在這個 function 可以接受不等數量的資料輸入了,
所以在改寫 -1我是以傳入3筆資料舉例、在改寫 -2我索性就只傳兩筆資料了,
一樣可以正常運作喔~

使用 ... 展開參數

讓我們承接改寫 -2的 function 並繼續

改寫 -2中我們已經獲得一個可以接受不等數量變數的 function 了,
但我們可不可以也動態決定要傳幾筆資料給這個 function 計算呢?

可以的!
只要在 call function 的地方對 array 使用 ... 就可以了!

<?php

print_r(calculateMd5ForObjects(
    ...$data->data
));

目前$data->data總共有 3 筆資料,所以這樣的語法等價於:

print_r(calculateMd5ForObjects(
    $data->data[0],
    $data->data[1],
    $data->data[2]
));

這樣子的 PHP 是不是一下子變得特別動態的感覺了呢?


上一篇
我來、我見、我宣告變數
下一篇
Array:流程控制、迭代操作
系列文
花式PHP31

尚未有邦友留言

立即登入留言