質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

2回答

932閲覧

Laravel5 Collectionの結合について

BlueBits

総合スコア57

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

0クリップ

投稿2019/02/13 03:11

編集2019/02/13 05:08

前提・実現したいこと

LaravelのCollection同士を結合
(イメージとしてはDB left join)
そのコマンドがあるかどうか?

データベース(案)

Collection出力の元となるデーターベースです。

users

idname
1名前1
2名前2
3名前3

titles

idname
1タイトル1
2タイトル2
3タイトル3

items

idtitle_idname
11アイテム1
21アイテム2
31アイテム3
42アイテム4
52アイテム5
62アイテム6
73アイテム7
83アイテム8
93アイテム9

datas

iduser_idtitle_iditem_id
1112
2125
3138

以上のデータベースから
datasより名前1(user_id 1)のデータを以下のように出力し

結果

php

1$collection = collect([ 2 ['id' => 1, 'title' => 'タイトル1', 'value' => 2,'name' => 'アイテム2'], 3 ['id' => 2, 'title' => 'タイトル2', 'value' => 5,'name' => 'アイテム5'], 4 ['id' => 3, 'title' => 'タイトル3', 'value' => 8,'name' => 'アイテム8'] 5]);

以上の構成であればデーターベースでやれば簡単なのですが、

それをCollectionで似たようなことが、できないかというのが今回の質問の意図です。

また理由の1つに、上記のテーブルが一部jsonデータで保存されていた場合にどのようにすればいいかと方法に悩んでしまいました。
Collectionであれば以下の方法でjsonデータをcollect化できますので。。

collect(json_encode(jsonデータ))

質問

2つのCollectionを結合して1つのCollectionデータを作成を考えています。

php

1$collection_a = collect([ 2 ['id' => 1, 'value' => 2], 3 ['id' => 2, 'value' => 5], 4 ['id' => 3, 'value' => 8], 5]); 6 7$collection_b = collect([ 8 ['id' => 1, 'title' => 'タイトル1', 9 'items'=>[ 10 ['id' => 1, 'name' => 'アイテム1'], 11 ['id' => 2, 'name' => 'アイテム2'], 12 ['id' => 3, 'name' => 'アイテム3'] 13 ] 14 ], 15 ['id' => 2, 'title' => 'タイトル2', 16 'items'=>[ 17 ['id' => 4, 'name' => 'アイテム4'], 18 ['id' => 5, 'name' => 'アイテム5'], 19 ['id' => 6, 'name' => 'アイテム6'] 20 ] 21 ], 22 ['id' => 3, 'title' => 'タイトル3', 23 'items'=>[ 24 ['id' => 7, 'name' => 'アイテム7'], 25 ['id' => 8, 'name' => 'アイテム8'], 26 ['id' => 9, 'name' => 'アイテム9'] 27 ] 28 ] 29]);

以上の2つのCollectionを以下のように出力を考えています。

php

1$collection_c = collect([ 2 ['id' => 1, 'title' => 'タイトル1', 'value' => 2,'name' => 'アイテム2'], 3 ['id' => 2, 'title' => 'タイトル2', 'value' => 5,'name' => 'アイテム5'], 4 ['id' => 3, 'title' => 'タイトル3', 'value' => 8,'name' => 'アイテム8'] 5]);

foreachで回す方法しかないのでしょうか?

まわりくどい方法は思いつくのですが
Laravel自体はまだ始めたばっかで適切なコマンド・方法があるかと思った次第です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/02/13 03:55

スペルミスがかなり目に付いてしまうので修正していただければと。 Larvel larabel ではなくLaravel
m.ts10806

2019/02/13 04:28 編集

要件確認です。 collect()されたものをマージということですよね? 提示されている配列は仮のものとは思いますが、大目的が別にあるのでしたらそれもあった方がよいかもしれません。 ~~~最後1行余計でした。編集削除しました。
BlueBits

2019/02/13 04:28

おっしゃる通りです。あとでcollectという面で言いますと元々、collection_a,bはEloquentでDBから出力したイメージになります。なのでDB出力時にcollection_cに調整してやればとも思います。 データベース部分も含めて全体イメージを質問に追加します。
guest

回答2

0

探すのはcollectionにお任せするとしても、やっぱり大元をは自分で回さざるを得なさそうな・・

php

1$collection_c = $collection_a->map(function($_a,$_)use($collection_b){ 2 $_a['title'] = $_a['name'] = null; 3 4 //コレクションBから、b.id=a.idを探す 5 if($_b = $collection_b->where('id', $_a['id'])->first()){ 6 $_a['title']=$_b['title']; 7 //Bの中のitemsもcollectionにして、そこからb.items.id = a.valueを探す 8 $_items = collect($_b['items']); 9 if($_b_item = $_items->where('id', $_a['value'])->first()){ 10 $_a['name'] = $_b_item['name']; 11 } 12 } 13 return $_a; 14});

自分でforeachの入れ子を沢山書くよりはマシなのかなーという感じでしょうかねぇ^^;

投稿2019/02/13 07:19

mix-peach

総合スコア1910

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BlueBits

2019/02/13 07:34

すみません、解答いただいて自分で調べて解答書いてた間にアンサーいただいてました。 結局foreachの入れ子なのでそもそも構成が甘かったようです。 1人で開発しているので他の方の意見がお聞きできて嬉しいです。 ありがとうございます。
guest

0

ベストアンサー

あまり美しくないやり方かもしれませんが。(結局foreach使ったし・・・)

php

1$collection_c=$collection_a->map(function ($item_a,$key_a) use ($collection_b){ 2 $collection_b->map(function ($item_b,$key_b) use (&$item_a){ 3 if($item_b['id'] === $item_a['id']){ 4 foreach($item_b['items'] as $b_collect){ 5 if($b_collect['id'] === $item_a['value']){ 6 $item_a['title']=$item_b['title']; 7 $item_a['name']=$b_collect['name']; 8 return false; 9 } 10 } 11 } 12 }); 13 return $item_a; 14}); 15var_dump($collection_c->all()); 16 17/* 18 19array(3) { 20 [0]=> 21 array(4) { 22 ["id"]=> 23 int(1) 24 ["value"]=> 25 int(2) 26 ["title"]=> 27 string(13) "タイトル1" 28 ["name"]=> 29 string(13) "アイテム2" 30 } 31 [1]=> 32 array(4) { 33 ["id"]=> 34 int(2) 35 ["value"]=> 36 int(1) 37 ["title"]=> 38 string(13) "タイトル2" 39 ["name"]=> 40 string(13) "アイテム1" 41 } 42 [2]=> 43 array(4) { 44 ["id"]=> 45 int(3) 46 ["value"]=> 47 int(3) 48 ["title"]=> 49 string(13) "タイトル3" 50 ["name"]=> 51 string(13) "アイテム3" 52 } 53} 54*/

下記のような記事も参考にしてみてもいいかもしれません。

投稿2019/02/13 05:20

編集2019/02/13 05:23
m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

BlueBits

2019/02/13 07:20

ありがとうございます。頂いたコードを元に見直してみました。 $collection_c=$collection_a->map(function ($item_a,$key_a) use ($collection_b){ $find_collection = collect($collection_b->firstWhere('id','===',$item_a['id'])); $find_item = collect($find_collection->get('items'))->firstWhere('id','===',$item_a['value']); $item_a['title'] = $find_collection->get('title'); $item_a['name'] = $find_item['name']; return $item_a; }); $collection_c->dump(); foreach,ifをcollectのfirstWhereに変更して見た目だけスッキリしました。 内部処理的はよりまわりくどく同じ事をしていますのでなんとも言えませんが・・・ 構成の見直しのイメージになりました。ありがとうございます。
m.ts10806

2019/02/13 07:24

そうですね。Laravelっぽい作りになったと思います(別回答のほうが綺麗ですね。。)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問