Comments (7)
@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.
@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.
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.
@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.
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.
@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.
@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)
- Generate schema fail! HOT 1
- Exception Undefined array key "schemaExtensions" HOT 1
- Clear Cache (private) HOT 1
- Segmentation fault when handling large payloads HOT 8
- Requesting local scopes can pass parameters HOT 1
- New directive that mirrors functionality of `whereHas` for relations (not `@whereHasConditions`) HOT 1
- `make setup` failed on macOS
- Access context in `FieldMiddleware` HOT 3
- CanArgs is defined twice in schema-directives.graphql
- `extend scalar X` directives are lost
- @canFind is missing "model" argument in graphql definition HOT 1
- Allow to customize the unique key for `PaginatedModelsLoader`
- artisan lighthouse:union stub appears to be incorrect HOT 1
- Problem with subscription middleware HOT 2
- An error occurs in the SubscriptionRegistry when sending a subscription event via Subscription::broadcast with Laravel Octane (Swoole) HOT 5
- Laravel v11 support dependancy missing
- Enum Support for Morph Types HOT 1
- Mutation transaction seem not work HOT 4
- Failed to find class App\GraphQl\Queries\TodoQuery in namespaces [] for directive @paginate
- @whereNull and @whereNotNull No directive found!
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lighthouse.