Reputation: 96
I'm having some issues wrapping my head around nested mutations with Lighthouse.
I've got two models that are related: Ams\Account
hasMany Ams\Contact
. This is the Ams\Contact
model:
namespace App\Models\Ams;
use Eloquent as Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Contact extends Model
{
use SoftDeletes;
public $table = 'ams_contacts';
protected $dates = ['deleted_at'];
public $fillable = [
'ams_account_id',
'forename',
'surname',
'active',
'email'
];
protected $casts = [
'forename' => 'string',
'surname' => 'string',
'active' => 'boolean',
'email' => 'string'
];
public static $rules = [
'ams_account_id' => 'required',
'forename' => 'required',
'surname' => 'required',
'email' => 'required|email'
];
public function amsAccount(): BelongsTo
{
return $this->belongsTo(\App\Models\Ams\Account::class, 'ams_account_id', 'id');
}
}
My GraphQL schema file looks like this:
"A datetime string with format `Y-m-d H:i:s`, e.g. `2018-01-01 13:00:00`."
scalar DateTime @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\DateTime")
"A date string with format `Y-m-d`, e.g. `2011-05-23`."
scalar Date @scalar(class: "Nuwave\\Lighthouse\\Schema\\Types\\Scalars\\Date")
type Query {
amsAccounts: [AmsAccount!]! @paginate(defaultCount: 10 model: "App\\Models\\Ams\\Account")
amsAccount(id: ID @globalId): AmsAccount @find(model: "App\\Models\\Ams\\Account")
amsContacts: [AmsContact!]! @paginate(defaultCount: 10 model: "App\\Models\\Ams\\Contact")
amsContact(id: ID @globalId): AmsContact @find(model: "App\\Models\\Ams\\Contact")
}
type Mutation {
createAmsAccount(
input: CreateAmsAccountInput! @spread
): AmsAccount @create(model: "App\\Models\\Ams\\Account")
updateAmsAccount(
input: UpdateAmsAccountInput! @spread
): AmsAccount @update(model: "App\\Models\\Ams\\Account")
deleteAmsAccount(
id: ID! @rules(apply: ["required"])
): AmsAccount @delete(model: "App\\Models\\Ams\\Account")
createAmsContact(
input: CreateAmsContactInput! @spread
): AmsContact @create(model: "App\\Models\\Ams\\Contact")
updateAmsContact(
input: UpdateAmsContactInput! @spread
): AmsContact @update(model: "App\\Models\\Ams\\Contact")
deleteAmsContact(
id: ID! @rules(apply: ["required"])
): AmsContact @delete(model: "App\\Models\\Ams\\Contact")
}
type AmsAccount @node(namespace: "App\\Models\\Ams\\Account") {
id: ID! @globalId
name: String!
url: String
telephone: String!
created_at: DateTime!
updated_at: DateTime!
}
input CreateAmsAccountInput {
name: String!
url: String
telephone: String!
}
input UpdateAmsAccountInput {
id: ID!
name: String!
url: String
telephone: String!
}
input UpsertAmsAccountInput {
id: ID!
name: String!
url: String
telephone: String!
}
type AmsContact @node(namespace: "App\\Models\\Ams\\Contact") {
id: ID! @globalId
forename: String!
surname: String!
active: Boolean
email: String!
amsAccount: AmsAccount! @belongsTo
created_at: DateTime!
updated_at: DateTime!
}
input CreateAmsContactInput {
forename: String!
surname: String!
active: Boolean
email: String!
amsAccount: CreateAmsAccountBelongsTo
}
input UpdateAmsContactInput {
id: ID!
forename: String!
surname: String!
active: Boolean
email: String!
amsAccount: UpdateAmsAccountBelongsTo
}
input UpsertAmsContactInput {
id: ID!
forename: String!
surname: String!
active: Boolean
email: String!
amsAccount: UpsertAmsAccountBelongsTo
}
input CreateAmsAccountBelongsTo {
connect: ID
create: CreateAmsAccountInput
update: UpdateAmsAccountInput
upsert: UpsertAmsAccountInput
}
input UpdateAmsAccountBelongsTo {
connect: ID
create: CreateAmsAccountInput
update: UpdateAmsAccountInput
upsert: UpsertAmsAccountInput
disconnect: Boolean
delete: Boolean
}
input UpsertAmsAccountBelongsTo {
connect: ID
create: CreateAmsAccountInput
update: UpdateAmsAccountInput
upsert: UpsertAmsAccountInput
disconnect: Boolean
delete: Boolean
}
When I try and run the following mutation in the playground:
mutation {
createAmsContact(
input: {
forename: "Jane"
surname: "Doe"
active: true
email: "[email protected]"
amsAccount: {
connect: 1
}
}
) {
id
forename
surname
amsAccount: id
}
}
I get an error about the following error message:
"debugMessage": "SQLSTATE[HY000]: General error: 1364 Field 'ams_account_id' doesn't have a default value (SQL: insert into `ams_contacts` (`forename`, `surname`, `active`, `email`, `updated_at`, `created_at`) values (Jane, Doe, 1, [email protected], 2020-04-12 15:31:52, 2020-04-12 15:31:52))"
I've tried a number of fixes and suggestions from around the web, and as far as I can see my schema follows the defined format from the documentation, but I cannot fathom out why it's not working.
I've also confirmed that the simple mutation for the account work fine. I also get a similar error message when I try to create a new account at the same time as the contact.
My inclination is that it's to do with the namespaces of the different models, but I can't imagine I'm the first to have this requirement, nor can I find any references to how to overcome this.
Any and all help will be greatly appreciated.
Upvotes: 0
Views: 230
Reputation: 96
So I wasn't actually a million miles from the mark with my Namespace problem.
The problem lies with the Model file, specifically here:
public function amsAccount(): BelongsTo
{
return $this->belongsTo(\App\Models\Ams\Account::class, 'ams_account_id', 'id');
}
The issue is that the BelongsTo
had not been specified in the use
clauses at the start of the model class. As such the return class type could not be detected properly.
As such it was necessary to add the following to the use
clauses at the top of the file:
use Illuminate\Database\Eloquent\Relations\BelongsTo;
This applies to other relationship types.
This is what the Documentation states, but is so subtle that it didn't click.
RTFM.
Thanks for all who looked and hope this helps someone else in the future.
Upvotes: 2