nuwave / lighthouse

A framework for serving GraphQL from Laravel
https://lighthouse-php.com
MIT License
3.36k stars 437 forks source link

Dealing with attributes on the pivot table of a BelongsToMany relation #691

Closed TheJoeSchr closed 4 years ago

TheJoeSchr commented 5 years ago

Situation

I'm trying to implement @update on a belongsToMany relationship. The pivot table also has columns I want to update, like this:

class Patient extends Model
{
    // many to many RELATIONSHIPS
    public function medications(): BelongsToMany
    {
        return $this->belongsToMany(Medication::class, 'patients__medications', 'patient_id', 'medication_id')->withPivot('dose_mg', 'is_rescue_medication'); //->as("details");
    }
}

my example schema:

#schema.graphql excerpts
# Mutations {}
updateMedication(input: MedicationInput): Medication! @update(flatten: true)

# Types
# -- Medication
input MedicationInput {
    id: ID
    name: String
    pivot: MedicationDetailsInput
}

input MedicationDetailsInput {
    patient_id: ID
    medication_id: ID
    dose_mg: Float
    is_rescue_medication: Boolean
}
input MedicationRelation {
  update: [MedicationInput]
  connect: [MedicationDetailsInput]
  disconnect: [ID]
  create: [MedicationInput]
  delete: [MedicationInput]
  sync: [MedicationDetailsInput]
}

Problem

I get an SQL error that laravel can't find the columns (of course, they don't exist because they are on the pivot table) on the related table to update.

I debugged it down to the executeUpdate function in MutationExecutor.php , where the pivot property is still inside $remaining and gets treated as a normal property on the related Model instead of the special case of being pivot columns.

Expected

pivot columns should be updated,

Workarounds

there was a workaround suggested:

You can treat your BelongsTo relation simply as two BelongsTo relationships to work around this.

by @spawnia in this issue thread #549

spawnia commented 5 years ago

For future-reference, here is an excerpt from the discussion of #692:

When you think about what the BelongsToMany relationship actually is, you will find that it is in fact comprised of a HasMany and a BelongsTo relationship.

In terms of your concrete example, you should be able to update a medication like this:

mutation {
    updateMedication(input: {
        id: 1
        name: "Lysergicream"
        # That would be a HasMany relationship from Mediation to the pivot model
        medicationUser: {
            update: [{
                dose_mg: 11
                # This is a belongsTo relationship from your pivot model to User
                user: {
                    connect: 1
                }
           }]
        }
    }) {
        id
        name
        # Will return a list, as this is a HasMany relationship
        medicationUser {
            dose_mg
            # A single BelongsTo
            user {
                 id
                 name
            }
         }
    }
}

I think we should add a section about how to deal with pivot attributes to the docs. Queries are affected too and should be considered.

spawnia commented 4 years ago

@JoeSchr you can now use nested mutations to do this directly and in a convenient way: https://github.com/nuwave/lighthouse/pull/1110

TheJoeSchr commented 4 years ago

Thanks. Meanwhile I made my custom fork to work around this, but it seems it's finally time to update to this release!

AbdElrahmaN31 commented 2 years ago

@spawnia How can I write a type that expresses this relationship (beongsToMany + Pivot columns)?

spawnia commented 2 years ago

You can use the following channels to ask support questions:

This repository and the issue tracker are used to advance the development of Lighthouse.