Array 助手(ArrayHelper)

2018-02-24 15:40 更新

數(shù)組助手類(lèi)

除了PHP中豐富的數(shù)組函數(shù)集, Yii 數(shù)組助手類(lèi)提供了額外的靜態(tài)方法,讓你更高效地處理數(shù)組。

獲取值

用原生PHP從一個(gè)對(duì)象、數(shù)組、或者包含這兩者的一個(gè)復(fù)雜數(shù)據(jù)結(jié)構(gòu)中獲取數(shù)據(jù)是非常繁瑣的。 你首先得使用isset?檢查 key 是否存在, 然后如果存在你就獲取它,如果不存在, 則提供一個(gè)默認(rèn)返回值:

class User
{
    public $name = 'Alex';
}

$array = [
    'foo' => [
        'bar' => new User(),
    ]
];

$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;

Yii 提供了一個(gè)非常方便的方法來(lái)做這件事:

$value = ArrayHelper::getValue($array, 'foo.bar.name');

方法的第一個(gè)參數(shù)是我們從哪里獲取值。第二個(gè)參數(shù)指定了如何獲取數(shù)據(jù), 它可以是下述幾種類(lèi)型中的一個(gè):

  • 數(shù)組鍵名或者欲從中取值的對(duì)象的屬性名稱;
  • 以點(diǎn)號(hào)分割的數(shù)組鍵名或者對(duì)象屬性名稱組成的字符串,上例中使用的參數(shù)類(lèi)型就是該類(lèi)型;
  • 返回一個(gè)值的回調(diào)函數(shù)。

回調(diào)函數(shù)如下例所示:

$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
    return $user->firstName . ' ' . $user->lastName;
});

第三個(gè)可選的參數(shù)如果沒(méi)有給定值,則默認(rèn)為?null,如下例所示:

$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');

對(duì)于取到值后想要立即從數(shù)組中刪除的情況,你可以使用?remove?方法:

$array = ['type' => 'A', 'options' => [1, 2]];
$type = ArrayHelper::remove($array, 'type');

執(zhí)行了上述代碼之后,?$array?將包含?['options' => [1, 2]]?并且?$type?將會(huì)是?A?。 注意和?getValue?方法不同的是,remove?方法只支持簡(jiǎn)單鍵名。

檢查鍵名的存在

ArrayHelper::keyExists?工作原理和array_key_exists差不多,除了 它還可支持大小寫(xiě)不敏感的鍵名比較,比如:

$data1 = [
    'userName' => 'Alex',
];

$data2 = [
    'username' => 'Carsten',
];

if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
    echo "Please provide username.";
}

檢索列

通常你要從多行數(shù)據(jù)或者多個(gè)對(duì)象構(gòu)成的數(shù)組中獲取某列的值,一個(gè)普通的例子是獲取id值列表。

$data = [
    ['id' => '123', 'data' => 'abc'],
    ['id' => '345', 'data' => 'def'],
];
$ids = ArrayHelper::getColumn($array, 'id');

結(jié)果將是?['123', '345']。

如果需要額外的轉(zhuǎn)換或者取值的方法比較復(fù)雜, 第二參數(shù)可以指定一個(gè)匿名函數(shù):

$result = ArrayHelper::getColumn($array, function ($element) {
    return $element['id'];
});

重建數(shù)組索引

按一個(gè)指定的鍵名重新索引一個(gè)數(shù)組,可以用?index?方法。輸入的數(shù)組應(yīng)該是多維數(shù)組或者是一個(gè)對(duì)象數(shù)組。 鍵名(譯者注:第二個(gè)參數(shù))可以是子數(shù)組的鍵名、對(duì)象的屬性名, 也可以是一個(gè)返回給定元素?cái)?shù)組鍵值的匿名函數(shù)。

如果一個(gè)鍵值(譯者注:第二個(gè)參數(shù)對(duì)應(yīng)的值)是 null,相應(yīng)的數(shù)組元素將被丟棄并且不會(huì)放入到結(jié)果中,例如,

$array = [
    ['id' => '123', 'data' => 'abc'],
    ['id' => '345', 'data' => 'def'],
];
$result = ArrayHelper::index($array, 'id');
// the result is:
// [
//     '123' => ['id' => '123', 'data' => 'abc'],
//     '345' => ['id' => '345', 'data' => 'def'],
// ]

// using anonymous function
$result = ArrayHelper::index($array, function ($element) {
    return $element['id'];
});

建立哈希表

為了從一個(gè)多維數(shù)組或者一個(gè)對(duì)象數(shù)組中建立一個(gè)映射表(鍵值對(duì)),你可以使用?map方法.$from?和?$to?參數(shù)分別指定了欲構(gòu)建的映射表的鍵名和屬性名。 根據(jù)需要,你可以按照一個(gè)分組字段?$group?將映射表進(jìn)行分組,例如。

$array = [
    ['id' => '123', 'name' => 'aaa', 'class' => 'x'],
    ['id' => '124', 'name' => 'bbb', 'class' => 'x'],
    ['id' => '345', 'name' => 'ccc', 'class' => 'y'],
);

$result = ArrayHelper::map($array, 'id', 'name');
// 結(jié)果是: 
// [
//     '123' => 'aaa',
//     '124' => 'bbb',
//     '345' => 'ccc',
// ]

$result = ArrayHelper::map($array, 'id', 'name', 'class');
// 結(jié)果是:
// [
//     'x' => [
//         '123' => 'aaa',
//         '124' => 'bbb',
//     ],
//     'y' => [
//         '345' => 'ccc',
//     ],
// ]

多維排序

multisort?方法可用來(lái)對(duì)嵌套數(shù)組或者對(duì)象數(shù)組進(jìn)行排序,可按一到多個(gè)鍵名排序,比如,

$data = [
    ['age' => 30, 'name' => 'Alexander'],
    ['age' => 30, 'name' => 'Brian'],
    ['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);

排序之后我們?cè)?$data?中得到的值如下所示:

[
    ['age' => 19, 'name' => 'Barney'],
    ['age' => 30, 'name' => 'Brian'],
    ['age' => 30, 'name' => 'Alexander'],
];

第二個(gè)參數(shù)指定排序的鍵名,如果是單鍵名的話可以是字符串,如果是多鍵名則是一個(gè)數(shù)組, 或者是如下例所示的一個(gè)匿名函數(shù):

ArrayHelper::multisort($data, function($item) {
    return isset($item['age']) ? ['age', 'name'] : 'name';
});

第三個(gè)參數(shù)表示增降順序。單鍵排序時(shí),它可以是?SORT_ASC?或者?SORT_DESC?之一。 如果是按多個(gè)鍵名排序,你可以用一個(gè)數(shù)組為各個(gè)鍵指定不同的順序。

最后一個(gè)參數(shù)(譯者注:第四個(gè)參數(shù))是PHP的排序標(biāo)識(shí)(sort flag),可使用的值和調(diào)用PHP?sort()?函數(shù)時(shí)傳遞的值一樣。

檢測(cè)數(shù)組類(lèi)型

想知道一個(gè)數(shù)組是索引數(shù)組還是聯(lián)合數(shù)組很方便,這有個(gè)例子:

// 不指定鍵名的數(shù)組
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);

// 所有鍵名都是字符串
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);

HTML 編碼和解碼值

為了將字符串?dāng)?shù)組中的特殊字符做 HTML 編解碼,你可以使用下列方法:

$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);

默認(rèn)情況只會(huì)對(duì)值做編碼(譯者注:原文中是編碼,應(yīng)為編解碼)。通過(guò)給第二個(gè)參數(shù)傳?false?,你也可以對(duì)鍵名做編碼。 編碼將默認(rèn)使用應(yīng)用程序的字符集,你可以通過(guò)第三個(gè)參數(shù)指定該字符集。

合并數(shù)組

  /**
    * 將兩個(gè)或者多個(gè)數(shù)組遞歸式的合并為一個(gè)數(shù)組。
    * 如果每個(gè)數(shù)組有一個(gè)元素的鍵名相同,
    * 那么后面元素的將覆蓋前面的元素(不同于 array_merge_recursive)。
    * 如果兩個(gè)數(shù)組都有相同鍵名的數(shù)組元素(譯者注:嵌套數(shù)組)
    * 則將引發(fā)遞歸合并。
    * 對(duì)數(shù)值型鍵名的元素,后面數(shù)組中的這些元素會(huì)被追加到前面數(shù)組中。
    * @param array $a 被合并的數(shù)組
    * @param array $b 合并的數(shù)組,你可以在第三、第四個(gè)
    * 參數(shù)中指定另外的合并數(shù)組,等等
    * @return 合并的結(jié)果數(shù)組 (原始數(shù)組不會(huì)被改變)
    */
    public static function merge($a, $b)

對(duì)象轉(zhuǎn)換為數(shù)組

你經(jīng)常要將一個(gè)對(duì)象或者對(duì)象的數(shù)組轉(zhuǎn)換成一個(gè)數(shù)組,常見(jiàn)的情形是,為了通過(guò)REST API提供數(shù)據(jù)數(shù)組(或其他使用方式), 將AR模型(活動(dòng)記錄模型)轉(zhuǎn)換成數(shù)組。如下代碼可完成這個(gè)工作:

$posts = Post::find()->limit(10)->all();
$data = ArrayHelper::toArray($posts, [
    'app\models\Post' => [
        'id',
        'title',
        // the key name in array result => property name
        'createTime' => 'created_at',
        // the key name in array result => anonymous function
        'length' => function ($post) {
            return strlen($post->content);
        },
    ],
]);

第一個(gè)參數(shù)包含我們想要轉(zhuǎn)換的數(shù)據(jù),在本例中,我們要轉(zhuǎn)換一個(gè)叫?Post?的 AR 模型。

第二個(gè)參數(shù)是每個(gè)類(lèi)的轉(zhuǎn)換映射表,我們?cè)诖嗽O(shè)置了一個(gè)Post?模型的映射。 每個(gè)映射數(shù)組包含一組的映射,每個(gè)映射可以是:

  • 一個(gè)要包含的照原樣的字段名(和類(lèi)中屬性的名稱一致);
  • 一個(gè)由你可隨意取名的鍵名和你想從中取值的模型列名組成的鍵值對(duì);
  • 一個(gè)由你可隨意取名的鍵名和有返回值的回調(diào)函數(shù)組成的鍵值對(duì);

這上面的轉(zhuǎn)換結(jié)果將會(huì)是:

[
    'id' => 123,
    'title' => 'test',
    'createTime' => '2013-01-01 12:00AM',
    'length' => 301,
]

也可以在一個(gè)特定的類(lèi)中實(shí)現(xiàn)yii\base\Arrayable接口, 從而為其對(duì)象提供默認(rèn)的轉(zhuǎn)換成數(shù)組的方法。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)