0

I've been scouring Stack for the last couple of hours, and while several seem related, nothing appears to be working correctly.

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.

A User hasMany Trips, and each Trip belongsToMany Users via a pivot table called trip_user. On the Trip model, I am eager loading things such as Todos and Users like this:

Trip.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:

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. I'm not sure why the ->filter() function isn't working (I am brand new to Laravel, so there's that).

Why isn't the ->filter working correctly?

EDIT Including the results from a 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" => "[email protected]"
        "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" => "[email protected]"
        "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" => "[email protected]"
        "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" => "[email protected]"
        "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
        ]
      ]
    ]
  ]
]
9
  • 1
    What does dd($trips->toArray()); show you? Commented Nov 18, 2020 at 21:20
  • It gives me an array with the two test trips that are in my database Commented Nov 18, 2020 at 21:22
  • 1
    Please edit your question to include the output. Text, not screenshot. Commented Nov 18, 2020 at 21:26
  • 1
    Do you want to return trips without current user in the relation? Commented Nov 18, 2020 at 21:33
  • 1
    It would make more sense to do this filtering at the relationship level using a scope or when you retrieve it. Commented Nov 18, 2020 at 21:44

1 Answer 1

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.

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();
Sign up to request clarification or add additional context in comments.

6 Comments

Ah I was just messing around with using the ->where function! When trying this out, I received a rather large error related to SQLSTATE: Integrity constraint violation: 1052 Column 'id' in where clause is ambiguous (SQL: select users.*, trip_user.trip_id` as pivot_trip_id, trip_user.user_id as pivot_user_id from users inner join trip_user on users.id = trip_user.user_id where trip_user.trip_id in (1, 2) and id != 1)",`
That removes the error, however it unfortunately still retains the current_user
How do you retrieve the user relation? if you refetch em, the constraint will be removed
I should probably mention that I have a pivot table with user_id and trip_id columns. When I eager_load users from a Trip, it pulls all associated users in through the pivot.
But im pretty certain this should work, how do you transform your trips for the api?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.