cakePHP使っててうれしいのが、Hashクラスが組み込まれていることです。
これはとっても便利なので、他のフレームワークを使う時でももし同等のものがなければコピーして使おうかと思っています。
サンプルコード
いくつか簡単な例をあげます。
1 2 3 4 5 6 7 8 |
$user = array( 'User'=>array( array('id'=>1, 'name'=>'エレン', 'group_id'=>1), array('id'=>2, 'name'=>'ミカサ', 'group_id'=>1), array('id'=>3, 'name'=>'アルミン', 'group_id'=>1), array('id'=>10, 'name'=>'ジャン', 'group_id'=>2), ) ); |
このような配列があるとして、
4番目のユーザーの名前を取り出したいとき
1 2 3 4 5 6 |
print_r( Hash::extract( $user, 'User.3.name' ) ); |
Result:
1 2 3 4 5 |
Result: Array ( [0] => ジャン ) |
Userの下の配列は数値キーで0から始まっているので4番目を指定するには3になります。説明無用とは思いますが念のため。
idが2のユーザーの名前を取り出したいとき
[配列名=配列値]の書式で条件式を書けます。
1 2 3 4 5 6 7 8 |
<?php print_r( Hash::extract( $user, 'User.{n}[id=2]' ) ); ?> |
Result:
1 2 3 4 5 6 7 8 9 10 |
Array ( [0] => Array ( [id] => 2 [name] => ミカサ [group_id] => 1 ) ) |
配列名がなければ配列番号でもいけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php $user = array( 'User'=>array( array(1, 'エレン', 1), array(2, 'ミカサ', 1), array(3, 'アルミン', 1), array(10, 'ジャン', 2), ) ); print_r( Hash::extract( $user, 'User.{n}[0=2]' ) ); |
Result:
1 2 3 4 5 6 7 8 9 10 |
Array ( [0] => Array ( [0] => 2 [1] => ミカサ [2] => 1 ) ) |
Hashクラスのマッチャで使える記号:
‘=’
‘!=’
‘>’
‘<‘
‘>=’
‘<=’
等号は==でなく=なので注意してください。
配列のキーをidにして必要なデータのみの配列を作りたい時
1 2 3 4 5 6 7 8 9 |
<?php print_r( Hash::combine( $user, 'User.{n}.id', 'User.{n}.name' ) ); ?> |
Result:
1 2 3 4 5 6 7 |
Array ( [1] => エレン [2] => ミカサ [3] => アルミン [10] => ジャン ) |
このようにすっきりした配列を作成できます。リンクリストなどを作るのに活躍します。
条件式で指定したデータの配列を生成する
combineとマッチャを組み合わせて使用するときに注意しないといけないのが、第2引数と第3引数、両方にマッチャを指定しないといけないことです。キーと値の数が合わないとfalseが返ってきます。
1 2 3 4 5 6 7 8 9 |
<?php print_r( Hash::combine( $user, 'User.{n}[group_id=1].id', 'User.{n}[group_id=1].name' ) ); ?> |
Result:
1 2 3 4 5 6 |
Array ( [1] => エレン [2] => ミカサ [3] => アルミン ) |
グループIDでグルーピングしたユーザー配列を生成する
2次元配列を作るにはcombineに引数を追加します。
1 2 3 4 5 6 7 8 9 10 |
<?php print_r( Hash::combine( $user, 'User.{n}.id', 'User.{n}.name', 'User.{n}.group_id' ) ); ?> |
Result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Array ( [1] => Array ( [1] => エレン [2] => ミカサ [3] => アルミン ) [2] => Array ( [10] => ジャン ) ) |
group_idでユーザーを分けることが出来ましたね。
複雑な階層の多次元配列を扱う
不特定のキーを表すのに{n}と{s}があり、nが数値キー、sは文字列キーに対応しています。Hashパス構文の中に何個でも出現して構いません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
$user = array( 'User' => array( array( 'id' => 1, 'name' => 'エレン', 'items' => array( 'armor' => array( array('id' => 1, 'name' => '立体機動装置'), array('id' => 2, 'name' => 'ガスマスク') ), 'weapon' => array( array('id' => 3, 'name' => '超硬質スチール・刃') ) ) ), array( 'id' => 2, 'name' => 'ミカサ', 'items' => array( 'armor' => array( array('id' => 1, 'name' => '立体機動装置'), ), 'weapon' => array( array('id' => 3, 'name' => '超硬質スチール・刃'), array('id' => 4, 'name' => 'ライフル'), ) ) ) ) ); print_r( Hash::combine( $user, 'User.{n}.items.{s}.{n}.id', 'User.{n}.items.{s}.{n}.name' ) ); |
Result:
1 2 3 4 5 6 7 |
Array ( [1] => 立体機動装置 [2] => ガスマスク [3] => 超硬質スチール・刃 [4] => ライフル ) |
キャラクターの持つアイテムリストができました。idをキーとすることで重複は省かれています。
sptinrfの結果を値に入れる
Hash::formatを使えばsprintfの結果を取り出せます。
1 |
pr(Hash::format($user, array('User.{n}.name', 'User.{n}.group_id'), '%s(%d)')); |
Result:
1 2 3 4 5 6 7 |
Array ( [0] => エレン(1) [1] => ミカサ(1) [2] => アルミン(1) [3] => ジャン(2) ) |
これをHash::combineでやるときには第3引数を配列にして、1番目にフォーマット文字列を入れます。
1 |
pr(Hash::combine($user, 'User.{n}.id', array('%s(%d)', 'User.{n}.name', 'User.{n}.group_id'))); |
Result:
1 2 3 4 5 6 7 |
Array ( [1] => エレン(1) [2] => ミカサ(1) [3] => アルミン(1) [10] => ジャン(2) ) |
ほかにもいろいろ便利ですが
文字列を生成したり、配列に値を加えたり削除したり、非常にいろんなことができますが、抽出系に絞って書いてみました。
cakePHPの公式ドキュメント「Hash」をみれば全部書いてますが、サンプルが少ないのでちょっと分かりにくいかもと思うところもあります。
これを参考に、配列を自由に扱えるようになるとデータの扱いもぐっと幅がでてくることでしょう。
最後に、進撃の巨人のキャラクター名をサンプルに使ったのは深い意味はないのでその辺のツッコミは無用でお願いします。