Giter VIP home page Giter VIP logo

Comments (7)

hailwood avatar hailwood commented on July 19, 2024 2

@kikoseijo I had originally thought about nesting them under the model, and I'd be happy to be wrong on this, but let's say we're displaying a page that lists all uncompleted tasks per user.

If user A is linked to task A with the pivot_field being foo and user B is linked to task A with the pivot_field being bar then when we again grab task A for user B's list, won't that also make it appear in user A's list that pivot_field is bar due to caching by ID in the frontend clients (relay/apollo)?

from lighthouse.

kikoseijo avatar kikoseijo commented on July 19, 2024

@hailwood did you see this?
https://github.com/chrissm79/lighthouse-belongs-to-many

I found very useful the getFieldAttribute on models to do most of the hard work on relationships.

#69 has, maybe, something related to this.

from lighthouse.

hailwood avatar hailwood commented on July 19, 2024

Hey @kikoseijo yep that works great for belongsToMany, unfortunately it doesn't help with the case where the relationship has extra data attached to it (e,g, if you want the date the car option was added)

from lighthouse.

kikoseijo avatar kikoseijo commented on July 19, 2024

@hailwood what about this?

type Task {
  title: String!
  pivot: TaskPivot
}

type TaskPivot {
  user_id: Int!
  task_id: Int!
  pivot_field: String
}

This works, here its a project for you to test it, last commits have the adjustments.

https://github.com/kikoseijo/lighthouse-example

Here its the query used:
https://github.com/kikoseijo/lighthouse-example/blob/master/GraphQL-references.md

from lighthouse.

kikoseijo avatar kikoseijo commented on July 19, 2024

Now I get you point @hailwood the cache error I see it happening if both users use same device. Relay cache its done inside devices, but you can use different stores and avoid caching problems, cache its not configured by default, needs be programmed, as far as I now in Relay.

I can clearly see your point and the problem when a server side cache its applied.

Pivot information will be always linked to the current user id, a way to go around could be (not sure) to use an unique root query, being this for example the user id, with a relationship to the Tasks. You cant just call give me task X, you must do something like give me user X task X.

I haven't worked server cache and cant go any further.

BTW: thanks for this excellent mental exercise, maybe the Boss can give us his thoughts on this.

from lighthouse.

chrissm79 avatar chrissm79 commented on July 19, 2024

@hailwood So my initial thoughts are pretty close to what @kikoseijo mentioned. Technically, you could do the majority of this the way it's was listed in the example, but we could benefit from a @pivot directive here as well.

So, w/out creating your own directive, you could do the following

type Job {
  tasks: [TaskPivot] @hasMany
}

type Task {
  title: String!
}

type TaskPivot implements Node 
  @node(
    resolver: "App\\Http\\GraphQL\\TaskPivot\\\NodeTest@resolveNode"
    typeResolver: "App\\Http\\GraphQL\\TaskPivot\\\NodeTest@resolveType"
  ) {
  _id: ID! @field(resolver: "App\\Http\\GraphQL\\TaskPivot@id")
  user_id: Int! @field(resolver: "App\\Http\\GraphQL\\TaskPivot@userId")
  task_id: Int! @field(resolver: "App\\Http\\GraphQL\\TaskPivot@taskId")
  completed: String @field(resolver: "App\\Http\\GraphQL\\TaskPivot@completed")
  task: Task @field(resolver: "App\\Http\\GraphQL\\TaskPivot@task")
}

Then your resolver class would look something like this:

use Nuwave\Lighthouse\Support\Traits\HandlesGlobalId;

class TaskPivotType
{
    use HandlesGlobalId;
    
    public function id($root)
    {
        // For a composite key you could do something like this:
        return $this->encodeGlobalId(
            'TaskPivot', 
            "{$root->pivot->user_id}-{$task->pivot->task_id}"
        );
    }

    public function completed($root)
    {
        return $root->pivot->completed;
    }

    public function task($root)
    {
        return $root;
    }

    public function resolveNode($id)
    {
        // This would be the custom composite key we created above
        list($userId, $taskId) = explode('-', $id);

        return \App\Task::find($taskId);
    }

    public function resolveType($value)
    {
        if ($value instanceof \App\Task) {
            return schema()->type('Task');
        }
    }
}

To be completely honest, I'm going off the top of my head so I haven't tested this but I believe this solves all your problems. I'll add a pivot directive that allows you to do the following which will save you from having to create a custom resolver for each field.:

type TaskPivot implements Node 
  @pivot(modelField: "task")
  @node(
    resolver: "App\\Http\\GraphQL\\TaskPivot\\\NodeTest@resolveNode"
    typeResolver: "App\\Http\\GraphQL\\TaskPivot\\\NodeTest@resolveType"
  ) {
  _id: ID! @field(resolver: "App\\Http\\GraphQL\\TaskPivot@id")
  user_id: Int!
  task_id: Int!
  completed: String
  task: Task
}

Let me know if you still see any issues here. Thanks @hailwood and @kikoseijo!!

from lighthouse.

JasonTheAdams avatar JasonTheAdams commented on July 19, 2024

@chrissm79 Did you ever take a stab at the @pivot directive? Seems like that would be incredibly useful! I'll definitely be needing to make strong use of pivot data in my current project so that would be awesome. As I improve I may try to take a stab at it myself, but I'm still wrapping my head around all of this.

from lighthouse.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.