除了 豐富的 PHP 陣列函式集 之外,Yii 陣列 helper 還提供了額外的靜態方法,讓您可以更有效率地處理陣列。
從陣列、物件或由兩者組成的複雜結構中檢索數值,使用標準 PHP 是相當重複乏味的。您必須先使用 isset
檢查鍵是否存在,如果存在則取得它,否則提供預設值。
class User
{
public $name = 'Alex';
}
$array = [
'foo' => [
'bar' => new User(),
]
];
$value = isset($array['foo']['bar']->name) ? $array['foo']['bar']->name : null;
Yii 提供了一個非常方便的方法來做到這一點。
$value = ArrayHelper::getValue($array, 'foo.bar.name');
第一個方法參數是我們要從哪裡取得數值。第二個參數指定如何取得資料。它可以是以下其中之一:
回呼應如下:
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
return $user->firstName . ' ' . $user->lastName;
});
第三個可選參數是預設值,如果未指定,則為 null
。可以如下使用:
$username = ArrayHelper::getValue($comment, 'user.username', 'Unknown');
$array = [
'key' => [
'in' => ['k' => 'value']
]
];
ArrayHelper::setValue($array, 'key.in', ['arr' => 'val']);
// the path to write the value in `$array` can be specified as an array
ArrayHelper::setValue($array, ['key', 'in'], ['arr' => 'val']);
結果,$array['key']['in']
的初始值將被新值覆寫。
[
'key' => [
'in' => ['arr' => 'val']
]
]
如果路徑包含不存在的鍵,它將被建立。
// if `$array['key']['in']['arr0']` is not empty, the value will be added to the array
ArrayHelper::setValue($array, 'key.in.arr0.arr1', 'val');
// if you want to completely override the value `$array['key']['in']['arr0']`
ArrayHelper::setValue($array, 'key.in.arr0', ['arr1' => 'val']);
結果將是:
[
'key' => [
'in' => [
'k' => 'value',
'arr0' => ['arr1' => 'val']
]
]
]
如果您想要取得一個數值,然後立即從陣列中移除它,您可以使用 remove
方法。
$array = ['type' => 'A', 'options' => [1, 2]];
$type = ArrayHelper::remove($array, 'type');
執行程式碼後,$array
將包含 ['options' => [1, 2]]
,而 $type
將為 A
。請注意,與 getValue
方法不同,remove
僅支援簡單的鍵名。
ArrayHelper::keyExists
的運作方式與 array_key_exists 相同,只是它也支援不區分大小寫的鍵比較。例如:
$data1 = [
'userName' => 'Alex',
];
$data2 = [
'username' => 'Carsten',
];
if (!ArrayHelper::keyExists('username', $data1, false) || !ArrayHelper::keyExists('username', $data2, false)) {
echo "Please provide username.";
}
通常您需要從資料列或物件陣列中取得數值欄位。常見的範例是取得 ID 列表。
$array = [
['id' => '123', 'data' => 'abc'],
['id' => '345', 'data' => 'def'],
];
$ids = ArrayHelper::getColumn($array, 'id');
結果將會是 ['123', '345']
。
如果需要額外的轉換,或者取得數值的方式很複雜,則第二個參數可以指定為匿名函式。
$result = ArrayHelper::getColumn($array, function ($element) {
return $element['id'];
});
為了根據指定的鍵索引陣列,可以使用 index
方法。輸入應該是多維陣列或物件陣列。$key
可以是子陣列的鍵名、物件的屬性名稱,或必須傳回將用作鍵的值的匿名函式。
$groups
屬性是一個鍵陣列,將用於根據指定的鍵將輸入陣列分組為一個或多個子陣列。
如果特定元素的 $key
屬性或其值為 null
且未定義 $groups
,則將捨棄陣列元素。否則,如果指定了 $groups
,則陣列元素將被添加到結果陣列中,而沒有任何鍵。
例如:
$array = [
['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
];
$result = ArrayHelper::index($array, 'id');
結果將是一個關聯陣列,其中鍵是 id
屬性的值。
[
'123' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop'],
'345' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
// The second element of an original array is overwritten by the last element because of the same id
]
作為 $key
傳遞的匿名函式,會產生相同的結果。
$result = ArrayHelper::index($array, function ($element) {
return $element['id'];
});
將 id
作為第三個參數傳遞,將會依 id
分組 $array
。
$result = ArrayHelper::index($array, null, 'id');
結果將是一個多維陣列,在第一層依 id
分組,在第二層未索引。
[
'123' => [
['id' => '123', 'data' => 'abc', 'device' => 'laptop']
],
'345' => [ // all elements with this index are present in the result array
['id' => '345', 'data' => 'def', 'device' => 'tablet'],
['id' => '345', 'data' => 'hgi', 'device' => 'smartphone'],
]
]
匿名函式也可以在分組陣列中使用。
$result = ArrayHelper::index($array, 'data', [function ($element) {
return $element['id'];
}, 'device']);
結果將是一個多維陣列,在第一層依 id
分組,在第二層依 device
分組,在第三層依 data
索引。
[
'123' => [
'laptop' => [
'abc' => ['id' => '123', 'data' => 'abc', 'device' => 'laptop']
]
],
'345' => [
'tablet' => [
'def' => ['id' => '345', 'data' => 'def', 'device' => 'tablet']
],
'smartphone' => [
'hgi' => ['id' => '345', 'data' => 'hgi', 'device' => 'smartphone']
]
]
]
為了從多維陣列或物件陣列建立地圖(鍵值對),您可以使用 map
方法。$from
和 $to
參數指定設定地圖的鍵名或屬性名稱。可選地,可以根據分組欄位 $group
進一步分組地圖。例如:
$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');
// the result is:
// [
// '123' => 'aaa',
// '124' => 'bbb',
// '345' => 'ccc',
// ]
$result = ArrayHelper::map($array, 'id', 'name', 'class');
// the result is:
// [
// 'x' => [
// '123' => 'aaa',
// '124' => 'bbb',
// ],
// 'y' => [
// '345' => 'ccc',
// ],
// ]
multisort
方法有助於依一個或多個鍵排序物件陣列或巢狀陣列。例如:
$data = [
['age' => 30, 'name' => 'Alexander'],
['age' => 30, 'name' => 'Brian'],
['age' => 19, 'name' => 'Barney'],
];
ArrayHelper::multisort($data, ['age', 'name'], [SORT_ASC, SORT_DESC]);
排序後,我們將在 $data
中得到以下內容:
[
['age' => 19, 'name' => 'Barney'],
['age' => 30, 'name' => 'Brian'],
['age' => 30, 'name' => 'Alexander'],
];
指定要排序的鍵的第二個參數可以是字串(如果它是單個鍵)、陣列(如果是多個鍵)或匿名函式,如下所示:
ArrayHelper::multisort($data, function($item) {
// sort by age if it exists or by name otherwise
return isset($item['age']) ? $item['age'] : $item['name'];
});
第三個參數是方向。在依單個鍵排序的情況下,它可以是 SORT_ASC
或 SORT_DESC
。如果依多個值排序,您可以透過提供排序方向陣列來不同地排序每個值。
最後一個參數是 PHP 排序標誌,它可以採用與傳遞給 PHP sort() 相同的值。
知道陣列是索引陣列還是關聯陣列很方便。以下是一個範例:
// no keys specified
$indexed = ['Qiang', 'Paul'];
echo ArrayHelper::isIndexed($indexed);
// all keys are strings
$associative = ['framework' => 'Yii', 'version' => '2.0'];
echo ArrayHelper::isAssociative($associative);
為了將字串陣列中的特殊字元編碼或解碼為 HTML 實體,您可以使用以下方法:
$encoded = ArrayHelper::htmlEncode($data);
$decoded = ArrayHelper::htmlDecode($data);
預設情況下,只會編碼數值。透過將第二個參數作為 false
傳遞,您也可以編碼陣列的鍵。編碼將使用應用程式字元集,並且可以透過第三個參數變更。
您可以使用 ArrayHelper::merge() 將兩個或多個陣列遞迴地合併為一個。如果每個陣列都有一個具有相同字串鍵值的元素,則後者將覆寫前者(與 array_merge_recursive() 不同)。如果兩個陣列都有陣列類型的元素且具有相同的鍵,則將執行遞迴合併。對於整數索引的元素,後一個陣列中的元素將附加到前一個陣列。您可以使用 yii\helpers\UnsetArrayValue 物件從先前的陣列中取消設定值,或使用 yii\helpers\ReplaceArrayValue 強制取代先前的值而不是遞迴合併。
例如:
$array1 = [
'name' => 'Yii',
'version' => '1.1',
'ids' => [
1,
],
'validDomains' => [
'example.com',
'www.example.com',
],
'emails' => [
'admin' => 'admin@example.com',
'dev' => 'dev@example.com',
],
];
$array2 = [
'version' => '2.0',
'ids' => [
2,
],
'validDomains' => new \yii\helpers\ReplaceArrayValue([
'yiiframework.com',
'www.yiiframework.com',
]),
'emails' => [
'dev' => new \yii\helpers\UnsetArrayValue(),
],
];
$result = ArrayHelper::merge($array1, $array2);
結果將是:
[
'name' => 'Yii',
'version' => '2.0',
'ids' => [
1,
2,
],
'validDomains' => [
'yiiframework.com',
'www.yiiframework.com',
],
'emails' => [
'admin' => 'admin@example.com',
],
]
通常您需要將物件或物件陣列轉換為陣列。最常見的情況是轉換 active record 模型,以便透過 REST API 提供資料陣列或以其他方式使用它。可以使用以下程式碼來完成此操作:
$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);
},
],
]);
第一個參數包含我們要轉換的資料。在我們的範例中,我們正在轉換 Post
AR 模型。
第二個參數是每個類別的轉換對應。我們正在為 Post
模型設定對應。每個對應陣列都包含一組對應。每個對應可以是:
上面單個模型的轉換結果將是:
[
'id' => 123,
'title' => 'test',
'createTime' => '2013-01-01 12:00AM',
'length' => 301,
]
可以透過在該類別中實作 Arrayable 介面,為特定類別提供將物件轉換為陣列的預設方式。
通常您需要檢查元素是否在陣列中,或一組元素是否是另一個元素的子集。雖然 PHP 提供了 in_array()
,但它不支援子集或 \Traversable
物件。
為了幫助進行這些種類的測試,yii\helpers\ArrayHelper 提供了 isIn() 和 isSubset(),它們的簽名與 in_array() 相同。
// true
ArrayHelper::isIn('a', ['a']);
// true
ArrayHelper::isIn('a', new ArrayObject(['a']));
// true
ArrayHelper::isSubset(new ArrayObject(['a', 'c']), new ArrayObject(['a', 'b', 'c']));
發現錯字或您認為此頁面需要改進?
在 github 上編輯它 !
註冊 或 登入 以發表評論。