folkloreinc / laravel-graphql

Facebook GraphQL for Laravel 5. It supports Relay, eloquent models, validation and GraphiQL.
1.76k stars 234 forks source link

Laravel + GraphQL + MongoDB Embeded Relation bug #324

Open Osvius opened 6 years ago

Osvius commented 6 years ago

So, in our project we're using Laravel 5.5 + MongoDB + GraphQL and I've realized that this connection is current not so perfect and has some problems. For notice I'm using https://github.com/jenssegers/laravel-mongodb . The problem was with using Embeded relation in mongo. I'll give an example from my code. This is a relation in User Model:

public function images()
    {
        return $this->embedsMany('App\Image');
    }

And this is from User Type for GraphQL:

public function fields()
    {
        return [
            '_id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the user'
            ],
            'name' => [
                'type' => Type::string(),
                'description' => 'The name of user'
            ],
            'images' => [
                'type' => Type::listOf(GraphQL::type('images'))
                'description' => 'List of user`s photos'
            ]
        ];
    }

If your run some query like:

query fetchUsers {
    users {
        name
        images {
            url
        }
    }
}

You`ll probably receive an error:

"data": {
  "users": null
},
"errors": [
        {
          "message": "Call to undefined method Jenssegers\\Mongodb\\Query\\Builder::getQualifiedForeignKeyName()",
          "locations": [
            {
              "line": 2,
              "column": 2
            }
          ],
                }
]

I've made small research and found that in \Rebing\GraphQL\Support\SelectFields file we have a method named handleFields that checks existing of method that return foreign key in current relation Class. But mongo library has its own method in Embeded relation for this purpose - getQualifiedParentKeyName() and ofc it doesn't supported by graphql lib. So I've just put new "if else" into the handleFields and it should be something like this:

$relation = call_user_func([app($parentType->config['model']), $key]);
                        // Add the foreign key here, if it's a 'belongsTo'/'belongsToMany' relation
                        if(method_exists($relation, 'getForeignKey'))
                        {
                            $foreignKey = $relation->getForeignKey();
                        }
                        else if(method_exists($relation, 'getQualifiedForeignPivotKeyName'))
                        {
                            $foreignKey = $relation->getQualifiedForeignPivotKeyName();
                        }
                        else if(method_exists($relation, 'getQualifiedParentKeyName'))
                        {
                            $foreignKey = $relation->getQualifiedParentKeyName();
                        }
                        else
                        {
                            $foreignKey = $relation->getQualifiedForeignKeyName();
                        }

I hope that this is will be helpful for someone else too. Also, perhaps this fix will be added in future updates for better work with mongo users.

kodeine commented 6 years ago

any luck with this?