[英]How to filter nested collection in Laravel?
I've been scouring Stack for the last couple of hours, and while several seem related, nothing appears to be working correctly.在过去的几个小时里,我一直在搜索 Stack,虽然有几个似乎相关,但似乎没有任何工作正常。
I have a GraphQL API running on Laravel, and am trying to filter out the current_user from a mutator so that I don't have to do it on the frontend.我有一个在 Laravel 上运行的 GraphQL API,我正在尝试从 mutator 中过滤掉 current_user,这样我就不必在前端执行此操作。
A User hasMany Trips, and each Trip belongsToMany Users via a pivot table called trip_user
.一个用户有许多行程,每个行程通过一个名为
trip_user
的数据透视表trip_user
多个用户。 On the Trip model, I am eager loading things such as Todos and Users like this:在 Trip 模型上,我很想加载诸如 Todos 和 Users 之类的东西:
Trip.php旅行.php
class Trip extends Model
{
protected $with = [
'todos', 'shopping_list_items', 'users'
];
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class);
}
// other relationships
}
Then in my TripQuery which returns my results to my GraphQL client, I am trying to return all of a user's trips, but filter out current_user, like so:然后在将结果返回给我的 GraphQL 客户端的 TripQuery 中,我试图返回用户的所有行程,但过滤掉 current_user,如下所示:
class TripsQuery
{
public function find_by_user($rootValue, array $args, GraphQLContext $context, ResolveInfo $resolveInfo)
{
$user = $context->user();
if ($user) {
// all trip friends and todos automatically eager loaded on the model
$trips = $user->trips()->get();
return $trips->each->users->filter(function ($friend) use ($user) {
return $friend->id !== $user->id;
});
}
return null;
}
}
When I run this however, the only user it's returning is current_user, and for some reason it's returning an empty array of Todos
, even though it should return 4 of them.然而,当我运行它时,它返回的唯一用户是 current_user,并且由于某种原因它返回一个空数组
Todos
,即使它应该返回其中的 4 个。 I'm not sure why the ->filter()
function isn't working (I am brand new to Laravel, so there's that).我不确定为什么
->filter()
函数不起作用(我是 Laravel 的新手,所以就是这样)。
Why isn't the ->filter
working correctly?为什么
->filter
不能正常工作?
EDIT Including the results from a dd()
:编辑包括来自
dd()
的结果:
array:2 [
0 => array:9 [
"id" => 1
"name" => "Trip 1"
"description" => "Planning for Trip 1"
"owner_id" => 1
"created_at" => "2020-11-18T06:28:45.000000Z"
"updated_at" => "2020-11-18T06:28:45.000000Z"
"todos" => array:4 [
0 => array:6 [
"id" => 1
"title" => "Book car rental"
"checked" => 0
"trip_id" => 1
"created_at" => "2020-11-18T17:00:46.000000Z"
"updated_at" => "2020-11-18T17:00:46.000000Z"
]
1 => array:6 [
"id" => 2
"title" => "Check in to flights"
"checked" => 0
"trip_id" => 1
"created_at" => "2020-11-18T17:00:46.000000Z"
"updated_at" => "2020-11-18T17:00:46.000000Z"
]
2 => array:6 [
"id" => 3
"title" => "Drop off dog at sitter"
"checked" => 1
"trip_id" => 1
"created_at" => "2020-11-18T17:00:46.000000Z"
"updated_at" => "2020-11-18T17:00:46.000000Z"
]
3 => array:6 [
"id" => 4
"title" => "Stop at store"
"checked" => 1
"trip_id" => 1
"created_at" => "2020-11-18T17:00:46.000000Z"
"updated_at" => "2020-11-18T17:00:46.000000Z"
]
]
"users" => array:3 [
0 => array:19 [
"id" => 1
"api_token" => null
"email" => "test@gmail.com"
"email_verified_at" => "2020-11-07T15:38:48.000000Z"
"avatar_url" => null
"created_at" => "2020-11-07T15:38:48.000000Z"
"updated_at" => "2020-11-16T20:55:02.000000Z"
"pivot" => array:2 [
"trip_id" => 1
"user_id" => 1
]
]
1 => array:19 [
"id" => 2
"api_token" => null
"email" => "michael.scott@gmail.com"
"email_verified_at" => "2020-11-07T15:38:48.000000Z"
"avatar_url" => null
"created_at" => "2020-11-07T15:38:48.000000Z"
"updated_at" => "2020-11-07T15:38:48.000000Z"
"pivot" => array:2 [
"trip_id" => 1
"user_id" => 2
]
]
2 => array:19 [
"id" => 3
"api_token" => null
"email" => "pam.beasley@gmail.com"
"email_verified_at" => "2020-11-07T15:38:48.000000Z"
"avatar_url" => null
"created_at" => "2020-11-07T15:38:48.000000Z"
"updated_at" => "2020-11-07T15:38:48.000000Z"
"pivot" => array:2 [
"trip_id" => 1
"user_id" => 3
]
]
]
]
1 => array:9 [
"id" => 2
"name" => "Trip 2"
"description" => "Trip 2 Description"
"owner_id" => 1
"created_at" => "2020-11-18T06:28:45.000000Z"
"updated_at" => "2020-11-18T06:28:45.000000Z"
"todos" => []
"shopping_list_items" => []
"users" => array:1 [
0 => array:19 [
"id" => 1
"api_token" => null
"email" => "benny.timkins@gmail.com"
"email_verified_at" => "2020-11-07T15:38:48.000000Z"
"avatar_url" => null
"created_at" => "2020-11-07T15:38:48.000000Z"
"updated_at" => "2020-11-16T20:55:02.000000Z"
"pivot" => array:2 [
"trip_id" => 2
"user_id" => 1
]
]
]
]
]
Each does only return current collection for chaining oportunity, does not mutate the collection .每个只返回当前集合以用于链接机会, 不会改变集合。
I think the correct solution from how it looks like you use GraphQL
, is to filter the eager loading using the with()
method and adding a query to it.我认为从您使用
GraphQL
,正确的解决方案是使用with()
方法过滤急切加载并向其添加查询。
return $user->trips()->with(['users' => function ($query) use ($user) {
$query->where('id', '!=', $user->id);
}])->get();
For better code style, never check for a condition, invert it and return early.为了更好的代码风格,永远不要检查条件,将其反转并尽早返回。
$user = $context->user();
if (! $user) {
return null;
}
return $user->trips()->with(['users' => function ($query) use ($user) {
$query->where('users.id', '!=', $user->id);
}])->get();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.