Làm thế nào để hợp nhất hai bộ sưu tập hùng hồn?


86

Tôi có một bảng câu hỏi và một bảng thẻ. Tôi muốn tìm nạp tất cả các câu hỏi từ các thẻ của một câu hỏi nhất định. Vì vậy, ví dụ: tôi có thể gắn các thẻ "Du lịch", "Xe lửa" và "Văn hóa" cho một câu hỏi nhất định. Tôi muốn có thể tìm nạp tất cả các câu hỏi cho ba thẻ đó. Có vẻ như điều khó khăn là mối quan hệ câu hỏi và thẻ là một mối quan hệ nhiều-nhiều được định nghĩa trong Eloquent như thuộc về ToMany.

Tôi đã nghĩ đến việc cố gắng hợp nhất các Bộ sưu tập câu hỏi như bên dưới:

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

It doesn't seem to work though. Doesn't seem to merge anything. Am I attempting this correctly? Also, is there perhaps a better way to fetch a row of rows in a many-to-many relationship in Eloquent?


Did you check the documentation about eager loading and the with method? Your issue could be easily resolved using a better eloquent query. Once I get behind a computer I'll write an example unless someone beat me to it.
Luceos

1
@Luceos with won't help. It's whereHas that is needed - like in the answer below.
Jarek Tkaczyk

yes, my mistake; you are correct
Luceos

Câu trả lời:


136

The merge method returns the merged collection, it doesn't mutate the original collection, thus you need to do the following

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

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

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

Applying the example to your code

$related = new Collection();

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

1
Tôi đang cố gắng tạo một danh sách phẳng từ một cái cây, sử dụng push là những gì tôi cần, nhưng phương pháp foreach thực sự hữu ích.
George

Hãy nhớ rằng bộ sưu tập Eloquent không hoạt động như Bộ sưu tập bình thường. chúng sử dụng getKeyđể hợp nhất các kết quả, vì vậyModel::all()->merge(Model::all())->count() === Model::all()->count()
xuất hiện

33

Các merge()phương pháp trên Collectionkhông thay đổi bộ sưu tập mà trên đó nó được gọi. Nó trả về một bộ sưu tập mới với dữ liệu mới đã được hợp nhất. Bạn sẽ cần:

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

Tuy nhiên, tôi nghĩ rằng bạn đang giải quyết vấn đề từ một góc độ sai.

Vì bạn đang tìm kiếm các câu hỏi đáp ứng một số tiêu chí nhất định, có lẽ sẽ dễ dàng hơn để truy vấn theo cách đó. các has()whereHas() phương thức được sử dụng để tạo truy vấn dựa trên sự tồn tại của một bản ghi liên quan.

Nếu bạn chỉ tìm kiếm câu hỏi có bất kỳ thẻ nào, bạn sẽ sử dụng has()phương pháp này. Vì bạn đang tìm kiếm các câu hỏi với một thẻ cụ thể, bạn sẽ sử dụng whereHas()để thêm điều kiện.

Vì vậy, nếu bạn muốn tất cả các câu hỏi có ít nhất một thẻ với 'Du lịch', 'Xe lửa' hoặc 'Văn hóa', truy vấn của bạn sẽ giống như sau:

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

Nếu bạn muốn tất cả các câu hỏi có cả ba thẻ đó, truy vấn của bạn sẽ giống như sau:

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

1
+, tuy nhiên, tùy chọn thứ 2 (tất cả các thẻ) mà bạn đề xuất có thể được đơn giản hóa: stackoverflow.com/a/24706347/784588
Jarek Tkaczyk

nhưng bạn không thể mã hóa các tên thẻ. Trong ví dụ này, câu hỏi xảy ra với các thẻ đó, nhưng trong các câu hỏi khác, các thẻ sẽ khác nhau
Allfarid Morales García


11

Hợp nhất hai bộ sưu tập hùng hồn khác nhau thành một và một số đối tượng tình cờ có cùng một id, một đối tượng sẽ ghi đè đối tượng kia. Thay vào đó, hãy sử dụng phương thức push () hoặc suy nghĩ lại cách tiếp cận vấn đề của bạn để tránh điều đó. Tham khảo trên web


Cảm ơn, điều này đã đưa tôi vào nhận xét được tìm thấy ở đây medium.com/@jeffparr_57441/… dường như thực hiện công việc một cách rõ ràng mà không ghi đè.
Đánh dấu

1

Tất cả đều không hoạt động đối với tôi trên các bộ sưu tập hùng hồn , các bộ sưu tập hùng hồn của laravel sử dụng khóa từ các mục mà tôi nghĩ là nguyên nhân gây ra sự cố hợp nhất, bạn cần lấy lại bộ sưu tập đầu tiên dưới dạng một mảng, đưa bộ sưu tập đó vào một bộ sưu tập mới và sau đó đẩy các mục khác vào bộ sưu tập mới;

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

0

Tạo một bộ sưu tập cơ sở mới cho mỗi bộ sưu tập hùng hồn, việc hợp nhất hoạt động đối với tôi.

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

Trong trường hợp này, không có sự kết hợp bởi các khóa chính của nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.