我有一个问题表和一个标签表。我想从给定问题的标签中获取所有问题。因此,例如,我可能会将标签“旅行”、“火车”和“文化”附加到给定问题上。我希望能够获取这三个标签的所有问题。看起来棘手的是问题和标签关系是在 Eloquent 中定义为 belongsToMany 的多对多关系。
我考虑过尝试合并问题集合如下:
foreach ($question->tags as $tag) {
if (!isset($related)) {
$related = $tag->questions;
} else {
$related->merge($tag->questions);
}
}
但它似乎不起作用。似乎没有合并任何东西。我是否正确地尝试了这个?另外,在 Eloquent 中是否有更好的方法来获取多对多关系中的一行行?
with
无济于事。需要的是 whereHas
- 就像下面的答案一样。
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()
添加条件。
因此,如果您想要所有至少有一个带有“旅行”、“火车”或“文化”标签的问题,您的查询将如下所示:
$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);
将两个不同的 eloquent 集合合并为一个,一些对象恰好具有相同的 id,一个会覆盖另一个。请改用 push() 方法或重新考虑解决问题的方法以避免这种情况。 Refer to web
为每个雄辩的集合创建一个新的基础集合,合并对我有用。
$foo = collect(Foo::all());
$bar = collect(Bar::all());
$merged = $foo->merge($bar);
在这种情况下,它的主键没有冲突。
我使用合并遇到了一些问题。所以我使用了concat。你可以像下面这样使用它。
$users = User::all();
$associates = Associate::all();
$userAndAssociate = $users->concat($associates);
所有这些都不适用于 eloquent 集合,laravel eloquent 集合使用我认为会导致合并问题的项目中的密钥,您需要将第一个集合作为数组取回,将其放入新集合中,然后将其他集合推入新系列;
public function getFixturesAttribute()
{
$fixtures = collect( $this->homeFixtures->all() );
$this->awayFixtures->each( function( $fixture ) use ( $fixtures ) {
$fixtures->push( $fixture );
});
return $fixtures;
}
对此我很抱歉,但从 PHP 7.4 开始,您可以这样做(最好使用 merge
)。
$foo = Foo::all();
$bar = Bar::all();
/** $foo will contain $foo + $bar */
$foo->push(...$bar);
我想补充一点,我发现 concat 方法似乎没有基于 ID 覆盖,而 merge 方法可以。 concat 似乎对我有用,而 merge 引起了问题。
getKey
来合并结果,所以Model::all()->merge(Model::all())->count() === Model::all()->count()