如何合并两个雄辩的集合


How to Merge Two Eloquent Collections?

我有一个问题表和一个标签表。我想从给定问题的标签中获取所有问题。例如,我可能会给给定的问题加上"旅行"、"火车"answers"文化"标签。我希望能够获取这三个标签的所有问题。问题在于,问题和标签的关系是一个多对多的关系,在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);
}

Collection上的merge()方法不修改调用它的集合。它返回一个合并了新数据的新集合。您需要:

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

如果您想要所有包含这三个标签的问题,您的查询将看起来像:

$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()方法代替,或者重新考虑解决问题的方法以避免这种情况。参考网页

为每个雄辩的集合创建一个新的基本集合。

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

我在使用merge时遇到了一些问题。所以我使用concat。你可以像下面这样使用它。

$users = User::all();
$associates = Associate::all();
$userAndAssociate = $users->concat($associates);

雄辩的集合上都不适合我,laravel雄辩的集合使用项目中的键,我认为这会导致合并问题,您需要将第一个集合作为数组返回,将其放入新集合中,然后将其他集合推入新集合;

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

我想补充一点,我发现concat方法似乎不会基于ID覆盖,而合并方法则会。Concat似乎为我工作,而合并引起的问题。

我很抱歉,但是从PHP 7.4开始,你可以这样做(最好使用merge)。

$foo = Foo::all();
$bar = Bar::all();
/** $foo will contain $foo + $bar */
$foo->push(...$bar);