如何合并两个雄辩的收藏?


85

我有一个问题表和一个标签表。我想从给定问题的标签中获取所有问题。因此,例如,我可能在给定问题上附加了“旅行”,“火车”和“文化”标签。我希望能够获取这三个标签的所有问题。看来棘手的是,问题和标签之间的关系是在Eloquent中定义为多对多(belongsToMany)的。

我考虑过尝试合并以下问题集合:

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

它似乎不起作用。似乎没有合并任何东西。我是否尝试正确?另外,也许有一种更好的方法可以在Eloquent中以多对多关系获取一行行吗?


您是否检查了有关预加载和with方法的文档?使用更好的口才查询可以轻松解决您的问题。一旦找到电脑,除非有人击败我,否则我将写一个例子。
Luceos 2015年

1
@Luceoswith不会帮助。这whereHas是需要的-如下面的答案。
Jarek Tkaczyk 2015年

是的,我的错;您是正确的
Luceos 2015年

Answers:


133

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

1
我试图从树上建立一个平面列表,我需要使用push,但是foreach方法确实有帮助。
乔治,

请记住,雄辩的收藏行为不像普通收藏那样。他们getKey用来合并结果,所以Model::all()->merge(Model::all())->count() === Model::all()->count()
就像

32

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

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

但是,我认为您从错误的角度解决问题。

由于您要查找的是满足特定条件的问题,因此以这种方式进行查询可能会更容易。该has()whereHas()方法用于基于相关记录是否存在的查询。

如果您只是在寻找带有任何标签的问题,则可以使用该has()方法。由于您要查找带有特定标签的问题,因此可以使用whereHas()添加条件。

因此,如果您希望所有带有“旅行”,“火车”或“文化”至少一个标签的问题,您的查询将类似于:

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

1
+,但是您建议的第二个(所有标签)选项可能会简化:stackoverflow.com/a/24706347/784588
Jarek Tkaczyk 2015年

但是您不能对标签名称进行硬编码。在此示例中,问题恰好具有这些标签,但是在其他问题中,标签将有所不同
Allfarid MoralesGarcía18年



1

雄辩的集合上,所有方法都不适合我,laravel雄辩的集合使用我认为会引起合并问题的项中的键,您需要将第一个集合以数组的形式返回,将其放入一个新的集合中,然后将其他集合推入新的收藏;

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

0

为每个雄辩的收藏创建一个新的基本收藏,合并对我有用。

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

在这种情况下,不必通过主键进行限制。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.