web-dev-qa-db-ja.com

2つの雄弁なコレクションをマージする方法は?

質問表とタグ表があります。特定の質問のタグからすべての質問を取得したい。したがって、たとえば、特定の質問に「旅行」、「電車」、「文化」のタグを付けることができます。これらの3つのタグに関するすべての質問を取得できるようにしたいと思います。難しいのは、質問とタグの関係がEloquentでbelongsToManyとして定義されている多対多であることです。

私は質問コレクションを以下のようにマージしようと考えました:

foreach ($question->tags as $tag) {
    if (!isset($related)) {
        $related = $tag->questions;
    } else {
        $related->merge($tag->questions);
    }
}

それは動作しないようです。何もマージしていないようです。これを正しく試みていますか?また、Eloquentで多対多の関係で行の行をフェッチするより良い方法はおそらくありますか?

52
Martyn

Mergeメソッドは、マージされたコレクションを返します。元のコレクションは変更されないため、次を実行する必要があります

$original = new Collection(['foo']);

$latest = new Collection(['bar']);

$merged = $original->merge($latest); // Contains foo and bar.

サンプルをコードに適用する

$related = new Collection();

foreach ($question->tags as $tag)
{
    $related = $related->merge($tag->questions);
}
95
Wader

Collectionmerge()メソッドは、呼び出されたコレクションを変更しません。新しいデータがマージされた新しいコレクションを返します。必要なものは次のとおりです。

$related = $related->merge($tag->questions);

ただし、間違った角度から問題に取り組んでいると思います。

特定の基準を満たす質問を探しているので、おそらくその方法で照会する方が簡単でしょう。 has()メソッドとwhereHas()メソッドは、関連レコードの存在に基づいてクエリを生成するために使用されます。

タグのある質問を探している場合は、has()メソッドを使用します。特定のタグを持つ質問を探しているので、whereHas()を使用して条件を追加します。

したがって、「旅行」、「列車」、または「文化」のいずれかのタグが少なくとも1つあるすべての質問が必要な場合、クエリは次のようになります。

$questions = Question::whereHas('tags', function($q) {
    $q->whereIn('name', ['Travel', 'Trains', 'Culture']);
})->get();

これら3つのタグすべてを含むすべての質問が必要な場合、クエリは次のようになります。

$questions = Question::whereHas('tags', function($q) {
    $q->where('name', 'Travel');
})->whereHas('tags', function($q) {
    $q->where('name', 'Trains');
})->whereHas('tags', function($q) {
    $q->where('name', 'Culture');
})->get();
20
patricus
$users = User::all();
$associates = Associate::all();

$userAndAssociate = $users->merge($associates);
8
sh6210

2つの異なる雄弁なコレクションを1つにマージすると、一部のオブジェクトは偶然同じIDを持ち、一方は他方を上書きします。代わりにPush()メソッドを使用するか、問題へのアプローチを再考して回避してください。 ウェブを参照

7
newbie2005

雄弁なコレクション、laravel雄弁なコレクションはアイテムのキーを使用しますと思うこれはマージの問題を引き起こすため、取得する必要があります最初のコレクションを配列として戻し、それを新しいコレクションに入れてから、他のコレクションを新しいコレクションにプッシュします。

public function getFixturesAttribute()
{
    $fixtures = collect( $this->homeFixtures->all() );
    $this->awayFixtures->each( function( $fixture ) use ( $fixtures ) {
        $fixtures->Push( $fixture );
    });
    return $fixtures;
}
0
Luke Snowden