豊富なPHP配列関数のセットに加えて、Yiiの配列ヘルパーは、配列をより効率的に扱うことができる追加の静的メソッドを提供します。
標準的な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');
最初のメソッド引数は、値を取得する場所です。2番目の引数は、データの取得方法を指定します。以下のいずれかになります。
コールバックは以下のようになります。
$fullName = ArrayHelper::getValue($user, function ($user, $defaultValue) {
return $user->firstName . ' ' . $user->lastName;
});
3番目のオプションの引数はデフォルト値で、指定されていない場合は`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']
となります。
追加の変換が必要な場合、または値の取得方法が複雑な場合、2番目の引数に無名関数として指定できます。
$result = ArrayHelper::getColumn($array, function ($element) {
return $element['id'];
});
指定されたキーに従って配列にインデックスを付けるには、index
メソッドを使用できます。入力は、多次元配列またはオブジェクトの配列のいずれかである必要があります。$key
は、サブ配列のキー名、オブジェクトのプロパティ名、またはキーとして使用される値を返す無名関数のいずれかになります。
$groups
属性は、指定されたキーに基づいて入力配列を1つ以上のサブ配列にグループ化するために使用されるキーの配列です。
特定の要素の$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'];
});
3番目の引数としてid
を渡すと、$array
がid
でグループ化されます。
$result = ArrayHelper::index($array, null, 'id');
結果は、最初のレベルでid
でグループ化され、2番目のレベルではインデックス付けされていない多次元配列になります。
[
'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
、2番目のレベルでdevice
でグループ化され、3番目のレベルで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
メソッドは、オブジェクトまたはネストされた配列の配列を1つ以上のキーでソートするのに役立ちます。例えば、
$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'],
];
ソートするキーを指定する2番目の引数は、単一キーの場合は文字列、複数のキーの場合は配列、または次の無名関数のいずれかになります。
ArrayHelper::multisort($data, function($item) {
// sort by age if it exists or by name otherwise
return isset($item['age']) ? $item['age'] : $item['name'];
});
3番目の引数は方向です。単一キーでソートする場合、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);
デフォルトでは値のみがエンコードされます。2番目の引数をfalse
として渡すことで、配列のキーもエンコードできます。エンコーディングはアプリケーションの文字セットを使用し、3番目の引数で変更できます。
ArrayHelper::merge()を使用して、2つ以上の配列を再帰的に1つにマージできます。各配列に同じ文字列キー値を持つ要素がある場合、後者は前者を上書きします(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',
],
]
オブジェクトまたはオブジェクトの配列を配列に変換する必要があることがよくあります。最も一般的なケースは、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モデルを変換しています。
2番目の引数は、クラスごとの変換マッピングです。Post
モデルのマッピングを設定しています。各マッピング配列には、一連のマッピングが含まれています。各マッピングは次のようになります。
単一モデルに対する上記の変換の結果は次のようになります。
[
'id' => 123,
'title' => 'test',
'createTime' => '2013-01-01 12:00AM',
'length' => 301,
]
そのクラスでArrayableインターフェースを実装することで、特定のクラスに対するオブジェクトを配列に変換するデフォルトの方法を提供できます。
要素が配列内にあるか、要素のセットが別のセットの部分集合であるかをチェックする必要があることがよくあります。PHPはin_array()
を提供していますが、これは部分集合または\Traversable
オブジェクトをサポートしていません。
これらの種類のテストを支援するために、yii\helpers\ArrayHelperは、in_array()と同じシグネチャを持つisIn()とisSubset()を提供します。
// 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で編集してください。 !
コメントするにはサインアップまたはログインしてください。