[php] 두 개의 Eloquent 컬렉션을 병합하는 방법은 무엇입니까?

질문 테이블과 태그 테이블이 있습니다. 주어진 질문의 태그에서 모든 질문을 가져오고 싶습니다. 예를 들어, 주어진 질문에 “Travel”, “Trains”및 “Culture”태그를 붙일 수 있습니다. 이 세 태그에 대한 모든 질문을 가져올 수 있기를 원합니다. 까다로운 점은 질문과 태그 관계가 Eloquent에서 belongsToMany로 정의 된 다 대다라는 것입니다.

다음과 같이 질문 모음을 병합하려고 생각했습니다.

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

그래도 작동하지 않는 것 같습니다. 아무것도 병합하지 않는 것 같습니다. 올바르게 시도하고 있습니까? 또한 Eloquent에서 다 대다 관계에서 행의 행을 가져 오는 더 좋은 방법이 있습니까?



답변

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);
}


답변

merge()메서드 Collection는 호출 된 컬렉션을 수정하지 않습니다. 새 데이터가 병합 된 새 컬렉션을 반환합니다. 다음이 필요합니다.

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

그러나 나는 당신이 잘못된 각도에서 문제를 다루고 있다고 생각합니다.

특정 기준을 충족하는 질문을 찾고 있으므로 그런 방식으로 쿼리하는 것이 더 쉬울 것입니다. has()whereHas()방법은 관련 기록의 존재를 기반으로 쿼리를 생성하는 데 사용됩니다.

태그가있는 질문을 찾고 있다면 has()방법을 사용합니다 . 특정 태그가있는 질문을 찾고 있으므로를 사용 whereHas()하여 조건을 추가합니다.

따라서 ‘Travel’, ‘Trains’또는 ‘Culture’중 하나 이상의 태그가있는 모든 질문을 원하는 경우 쿼리는 다음과 같습니다.

$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();


답변

$users = User::all();
$associates = Associate::all();

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


답변

두 개의 서로 다른 웅변적인 컬렉션을 하나로 병합하면 일부 개체는 동일한 ID를 가지며 하나는 다른 하나를 덮어 씁니다. 대신 push () 메서드를 사용하거나 문제에 대한 접근 방식을 다시 생각하여 문제를 피하십시오.
웹 참조


답변

모두 웅변 적 컬렉션 에서 저에게 적합하지 않습니다 . laravel 웅변 적 컬렉션 은 병합 문제를 일으키는 것으로 생각 되는 항목의 키를 사용합니다 . 첫 번째 컬렉션을 배열로 다시 가져 와서 새 컬렉션에 넣은 다음 다른 컬렉션을 밀어 넣어야합니다. 새로운 컬렉션;

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


답변

각 유창한 컬렉션에 대한 새로운 기본 컬렉션을 만들면 병합이 효과적입니다.

$foo = collect(Foo::all());
$bar = collect(Bar::all());
$merged = $foo->merge($bar);

이 경우 기본 키에 의해 충돌이 발생하지 않습니다.


답변